【C++基础】深浅拷贝解析

在C++中,在用一个对象初始化另一个对象时,只复制了成员,并没有复制资源,使两个对象同时指向了同一资源的复制方式称为浅复制,也就是我们说的浅拷贝。

浅拷贝

通俗的理解,浅拷贝,只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。

请看下面的代码:

//浅拷贝
class String{
public:
	String(const char* str = "")
		:_str(new char[strlen(str) + 1]){
		strcpy(_str, str);
	}
        //拷贝构造函数
         String(String& s) {
		_str = s._str;
	}
	String& operator=(String& s) {
		_str = s._str;
	}

private:
	char* _str;
};

上面的代码,其拷贝构造函数和赋值运算符重载时,都是用的浅拷贝,浅拷贝只拷贝指针

String s1("hello world");
String s2 = s1;
String s3;
s3 = s1;

如上代码,对象s1的成员变量_str开辟了一段内存空间,然后对象s2和s3的成员变量_str也指向这段内存空间,如图:

     

这样的后果就是,如果改变了s1、s2和s3中的任意一个对象的成员变量_str,就会导致其他两个的_str也被改变

其实如果不自己实现拷贝构造函数,编译器自动实现的话,就是实现的浅拷贝!

浅拷贝还有一个问题,例如在这个String类中,加上析构函数的代码:

~String() {
    delelte[] _str;
    _str = NULL;
}

如果对象s1和s2是浅拷贝的话,即使这两个对象没有被改动影响,但是出了作用域,调用析构函数的时候,会对一块内存空间释放两次。

深拷贝

上面我们发现,浅拷贝有许多问题,因此我们需要用到深拷贝,把拷贝构造函数和赋值运算符重载重写,代码如下:
String(const String& s)
	:_str(new char[strlen(s._str) + 1]){
	strcpy(_str, s._str);
}

String& operator=(const String& s) {
        if(&s != this) {
        delete[] _str;
	_str = new char[strlen(s._str) + 1];
        strcpy(_str, s._str);
    }
    return *this;
}

由代码可以看出,拷贝构造函数和赋值运算符重载的时候,会新开辟一段内存空间,然后再把传入的str的值拷贝一份,如图:

注意这段代码:

String& operator=(const String& s) {
        if(&s != this) {
        delete[] _str;
	_str = new char[strlen(s._str) + 1];
        strcpy(_str, s._str);
    }
    return *this; 
}

这个函数是赋值运算符重载,这种写法是传统写法,我在这里讲几个容易踩的坑

1.没有释放原先_str指向的内存空间,容易造成你内存泄露(现代写法不用手动去释放原有的内存空间)

2.判断是否是给自身赋值,如s1 = s1(这点需要注意)

总结

这篇博客只是简单的解释一下C++实现类的时候浅拷贝和深拷贝的区别,这两点也是很重要的知识点,如果编程过程中不注意就可能会出现各种bug。

使用浅拷贝可能会导致以下后果:

1.如果使用其中一个指针更改指向内存空间的内容,则其他的指针指向内存空间的值也会被改变

2.可能会造成对申请内存空间的重复释放

所以我们应该避免使用浅拷贝,在类中手动实现拷贝构造函数和赋值运算符重载



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值