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;
}

运行结果


相关文章
|
2月前
|
存储 算法 C++
【C/C++ Vector容量调整】理解C++ Vector:Reserve与Resize的区别与应用
【C/C++ Vector容量调整】理解C++ Vector:Reserve与Resize的区别与应用
128 1
|
2月前
|
存储 C语言 C++
1. 认识C++和C的区别
1. 认识C++和C的区别
50 0
|
2月前
|
编译器 C++ Python
【C/C++ 泡沫精选面试题02】深拷贝和浅拷贝之间的区别?
【C/C++ 泡沫精选面试题02】深拷贝和浅拷贝之间的区别?
57 1
|
19天前
|
存储 安全 C++
C++中的引用和指针:区别与应用
引用和指针在C++中都有其独特的优势和应用场景。引用更适合简洁、安全的代码,而指针提供了更大的灵活性和动态内存管理的能力。在实际编程中,根据需求选择适当的类型,能够编写出高效、可维护的代码。理解并正确使用这两种类型,是掌握C++编程的关键一步。
21 1
|
2月前
|
人工智能 机器人 编译器
【C/C++】g++ 与 gcc的区别
【C/C++】g++ 与 gcc的区别
|
25天前
|
编译器 C语言 C++
C++中.h和.hpp文件有什么区别?
C++中.h和.hpp文件有什么区别?
|
18天前
|
Java C++
Java和C++的一些区别
Java和C++的一些区别
|
25天前
|
C++
【C++系列】指针对象和对象指针的区别
这段内容介绍了C++中`ListNode`对象和指针的两种使用方式以及它们的区别。首先,`ListNode dummy(0); ListNode* cur = &dummy;创建了一个`ListNode`对象`dummy`在栈上,`cur`是`dummy`的地址。而`ListNode* dummy = new ListNode(0); ListNode* cur = dummy;`则在堆上分配了一个`ListNode`,`dummy`和`cur`都是指向该对象的指针。使用`&dummy`作为虚拟头节点简化链表操作,避免特殊处理。栈分配内存自动管理但生命周期受限,堆分配内存需手动释放且速度较慢。
|
2月前
|
存储 编译器 程序员
C++中的宏定义和字符串字面值的区别
C++中的宏定义和字符串字面值的区别
|
2月前
|
C语言 C++
从C语言到C++_13(string的模拟实现)深浅拷贝+传统/现代写法(下)
从C语言到C++_13(string的模拟实现)深浅拷贝+传统/现代写法
28 0