C++什么是深浅拷贝,深浅拷贝的区别?

简介: C++什么是深浅拷贝,深浅拷贝的区别?

浅拷贝

// 浅拷贝:
class String
{
public:
    String(const char *str) : _str(new char[strlen(str) + 1])
    {
        strcpy(_str, str);
    }
    String(const String &s) : _str(s._str)
    {
        // 浅拷贝的方式就是将类中的指针指向新的指针
        // 这样就是实现了两个执政指向同一空间
        // 缺点1:通过类1修改空间内容,类2的内容也回改变
        // 缺点2:如果通过类1释放该空间过后,再通过类2释放空间就会出错
    }
    String &operator=(const String &s)
    {
        if (this != &s)
        {
            _str = s._str;
        }
        //返回引用是为了连续的赋值
        return *this;
    }
    ~String()
    {
        cout << "String析构" << endl;
        // 释放申请来的空间
        if (_str)
        {
            delete[] _str;
        }
        // 防止野指针的出现
        _str = NULL;
    }
    char *_str_get()
    {
        return this->_str;
    }
    void _str_set(const char *s)
    {
        strcpy(_str, s);
    }
private:
    char *_str;
};

浅拷贝的方式就是将类中的指针指向新的指针

这样就是实现了两个执政指向同一空间

问题1:通过类1修改空间内容,类2的内容也回改变

问题2:如果通过类1释放该空间过后,再通过类2释放空间就会出错

深拷贝的写法

// 深拷贝:
class MyString
{
public:
    MyString(const char *s) : _str(new char[strlen(s) + 1])
    {
        strcpy(_str, s);
    }
    MyString(const MyString &s) : _str(NULL)
    {
        MyString temp(s._str);
        swap(_str, temp._str);
    }
    MyString &operator=(const MyString &s)
    {
        // 深拷贝的方式就是通过重新构造一个局部类temp获取新的指针
        // 然后通过swap交换两个类的指针,相当于使_str重新指向一个新开辟的空间
        // 因为是局部类,执行完函数过后相应的就会被释放掉
        if (this != &s)
        {
            MyString temp(s._str);
            swap(_str, temp._str);
        }
        //返回引用是为了连续的赋值
        return *this;
    }
    ~MyString()
    {
        cout << "MyString析构" << endl;
        if (_str)
        {
            delete[] _str;
        }
        _str = NULL;
    }
    char *_str_get()
    {
        return this->_str;
    }
    void _str_set(const char *s)
    {
        strcpy(_str, s);
    }
private:
    char *_str;
};

深拷贝的方式就是通过重新构造一个局部类temp获取新的指针

然后通过swap交换两个类的指针,相当于使_str重新指向一个新开辟的空间

因为是局部类,执行完函数过后相应的就会被释放掉

完整程序

#include <iostream>
#include <string.h>
using namespace std;
// 浅拷贝:
class String
{
public:
    String(const char *str) : _str(new char[strlen(str) + 1])
    {
        strcpy(_str, str);
    }
    String(const String &s) : _str(s._str)
    {
        // 浅拷贝的方式就是将类中的指针指向新的指针
        // 这样就是实现了两个执政指向同一空间
        // 缺点1:通过类1修改空间内容,类2的内容也回改变
        // 缺点2:如果通过类1释放该空间过后,再通过类2释放空间就会出错
    }
    String &operator=(const String &s)
    {
        if (this != &s)
        {
            _str = s._str;
        }
        //返回引用是为了连续的赋值
        return *this;
    }
    ~String()
    {
        cout << "String析构" << endl;
        // 释放申请来的空间
        if (_str)
        {
            delete[] _str;
        }
        // 防止野指针的出现
        _str = NULL;
    }
    char *_str_get()
    {
        return this->_str;
    }
    void _str_set(const char *s)
    {
        strcpy(_str, s);
    }
private:
    char *_str;
};
// 深拷贝:
class MyString
{
public:
    MyString(const char *s) : _str(new char[strlen(s) + 1])
    {
        strcpy(_str, s);
    }
    MyString(const MyString &s) : _str(NULL)
    {
        MyString temp(s._str);
        swap(_str, temp._str);
    }
    MyString &operator=(const MyString &s)
    {
        // 深拷贝的方式就是通过重新构造一个局部类temp获取新的指针
        // 然后通过swap交换两个类的指针,相当于使_str重新指向一个新开辟的空间
        // 因为是局部类,执行完函数过后相应的就会被释放掉
        if (this != &s)
        {
            MyString temp(s._str);
            swap(_str, temp._str);
        }
        //返回引用是为了连续的赋值
        return *this;
    }
    ~MyString()
    {
        cout << "MyString析构" << endl;
        if (_str)
        {
            delete[] _str;
        }
        _str = NULL;
    }
    char *_str_get()
    {
        return this->_str;
    }
    void _str_set(const char *s)
    {
        strcpy(_str, s);
    }
private:
    char *_str;
};
int main(int argc, char **argv)
{
    // 浅拷贝
    String x_str("hello");
    String y_str(x_str);
    char *per = x_str._str_get();
    cout << "x_str中成员指向的空间地址:" << static_cast<const void *>(per) << endl;
    per = y_str._str_get();
    cout << "y_str中成员指向的空间地址:" << static_cast<const void *>(per) << endl;
    cout << "x_str:" << x_str._str_get() << endl;
    cout << "y_str:" << y_str._str_get() << endl;
    y_str._str_set("aaa");
    cout << "x_str:" << x_str._str_get() << endl;
    cout << "y_str:" << y_str._str_get() << endl;
    // 深拷贝
    MyString m_str("world");
    MyString n_str(m_str);
    per = m_str._str_get();
    cout << "m_str中成员指向的空间地址:" << static_cast<const void *>(per) << endl;
    per = n_str._str_get();
    cout << "n_str中成员指向的空间地址:" << static_cast<const void *>(per) << endl;
    cout << "m_str:" << m_str._str_get() << endl;
    cout << "n_str:" << n_str._str_get() << endl;
    m_str._str_set("bbb");
    cout << "m_str:" << m_str._str_get() << endl;
    cout << "n_str:" << n_str._str_get() << endl;
    // 两个指针指向不同的空间
    return 0;
}

运行结果


相关文章
|
4月前
|
存储 C++ Cloud Native
云原生部署问题之C++ 中的 nullptr 和 NULL 区别如何解决
云原生部署问题之C++ 中的 nullptr 和 NULL 区别如何解决
57 0
|
23天前
|
存储 安全 编译器
在 C++中,引用和指针的区别
在C++中,引用和指针都是用于间接访问对象的工具,但它们有显著区别。引用是对象的别名,必须在定义时初始化且不可重新绑定;指针是一个变量,可以指向不同对象,也可为空。引用更安全,指针更灵活。
|
5月前
|
存储 安全 C++
C++中的引用和指针:区别与应用
引用和指针在C++中都有其独特的优势和应用场景。引用更适合简洁、安全的代码,而指针提供了更大的灵活性和动态内存管理的能力。在实际编程中,根据需求选择适当的类型,能够编写出高效、可维护的代码。理解并正确使用这两种类型,是掌握C++编程的关键一步。
74 1
|
1月前
|
C语言 C++
C 语言的关键字 static 和 C++ 的关键字 static 有什么区别
在C语言中,`static`关键字主要用于变量声明,使得该变量的作用域被限制在其被声明的函数内部,且在整个程序运行期间保留其值。而在C++中,除了继承了C的特性外,`static`还可以用于类成员,使该成员被所有类实例共享,同时在类外进行初始化。这使得C++中的`static`具有更广泛的应用场景,不仅限于控制变量的作用域和生存期。
53 10
|
1月前
|
C语言 C++
实现两个变量值的互换[C语言和C++的区别]
实现两个变量值的互换[C语言和C++的区别]
19 0
|
3月前
|
存储 编译器 C语言
C++内存管理(区别C语言)深度对比
C++内存管理(区别C语言)深度对比
82 5
|
4月前
|
Web App开发 Rust 分布式计算
Rust与C++的区别及使用问题之对于大量使用C++实现的产品来说,迁移到Rust的问题如何解决
Rust与C++的区别及使用问题之对于大量使用C++实现的产品来说,迁移到Rust的问题如何解决
|
4月前
|
Rust 安全 编译器
Rust与C++的区别及使用问题之Rust中的bound check对性能产生影响的问题如何解决
Rust与C++的区别及使用问题之Rust中的bound check对性能产生影响的问题如何解决
|
4月前
|
Rust 测试技术 编译器
Rust与C++的区别及使用问题之Rust项目中组织目录结构的问题如何解决
Rust与C++的区别及使用问题之Rust项目中组织目录结构的问题如何解决
|
3月前
|
缓存 C++ Windows
Inno setup 脚本判断 Microsoft Visual C++ Redistributable 不同版本区别
Inno setup 脚本判断 Microsoft Visual C++ Redistributable 不同版本区别