[置顶] 【C++】 浅析深浅拷贝
2016-05-26 12:25
295 查看
C++中深拷贝和浅拷贝的问题是很值得我们注意的知识点,如果编程中不注意,可能会出现疏忽,导致bug。本文就详细讲讲C++深浅拷贝的种种。
我们知道,对于一般对象:
缺省拷贝构造函数在拷贝过程中是按字节复制的,对于指针型成员变量只复制指针本身,而不复制指针所指向的目标--浅拷贝。
用图形象化为:
在进行对象复制后,事实上s1、s2里的成员指针 _str 都指向了一块内存空间(即内存空间共享了),在s1析构时,delete了成员指针 _str
所指向的内存空间,而s2析构时同样指向(此时已变成野指针)并且要释放这片已经被s1析构函数释放的内存空间,这就让同样一片内存空间出现了
“double free”
,从而出错。而浅拷贝还存在着一个问题,因为一片空间被两个不同的子对象共享了,只要其中的一个子对象改变了其中的值,那另一个对象的值也跟着改变。所以这不是我们想要的结果,同事也不是真正意义上的复制。
为了解决浅拷贝问题,我们引出深拷贝,即自定义拷贝构造函数,如下:
[code=cpp;toolbar:false">String(const String& s)
:_str(new char[strlen(s._str) + 1])
{
strcpy(_str , s._str);
}void operator=(const String& s)
{
if(_str != s._str)
{
strcpy(_str,s._str);
}
return *this;
}String& operator=(const String& s)
{
if(_str != s._str)
{
delete[] _str;
_str = new char[strlen(s._str) + 1];
strcpy(_str,s._str);
}
return *this;
}同时,也考虑到了自己给自己赋值的情况。
可是这样写就完善了吗?是否要再仔细思索一下,还存在问题吗?!其实我可以告诉你,这样的写法也顶多算个初级工程师的写法。前面说过,为了保证内存不泄露,我们前面 delete[] _str,然后我们在把new出来的空间给了_str,但是这样的问题是,你有考虑过
我们知道,对于一般对象:
) // +1是为了避免空字符串导致出错但是,编译器提供的缺省函数并不是十全十美的。
{
strcpy(_str , str);
}
// 浅拷贝
String(const String& s)
:_str(s._str)
{}
~String()
{
if(_str)
{
delete[] _str;
_str = NULL;
}
cout<<]运行结果:
我们发现,编译通过了,但是崩溃了 = =ll ,这就是浅拷贝带来的问题。
事实是,在对象拷贝过程中,如果没有自定义拷贝构造函数,系统会提供一个缺省的拷贝构造函数,缺省的拷贝构造函数对于基本类型的成员变量,按字节复制,对于类类型成员变量,调用其相应类型的拷贝构造函数。原型如下:String(const String& s)
{}
缺省拷贝构造函数在拷贝过程中是按字节复制的,对于指针型成员变量只复制指针本身,而不复制指针所指向的目标--浅拷贝。
用图形象化为:
在进行对象复制后,事实上s1、s2里的成员指针 _str 都指向了一块内存空间(即内存空间共享了),在s1析构时,delete了成员指针 _str
所指向的内存空间,而s2析构时同样指向(此时已变成野指针)并且要释放这片已经被s1析构函数释放的内存空间,这就让同样一片内存空间出现了
“double free”
,从而出错。而浅拷贝还存在着一个问题,因为一片空间被两个不同的子对象共享了,只要其中的一个子对象改变了其中的值,那另一个对象的值也跟着改变。所以这不是我们想要的结果,同事也不是真正意义上的复制。
为了解决浅拷贝问题,我们引出深拷贝,即自定义拷贝构造函数,如下:
[code=cpp;toolbar:false">String(const String& s)
:_str(new char[strlen(s._str) + 1])
{
strcpy(_str , s._str);
}void operator=(const String& s)
{
if(_str != s._str)
{
strcpy(_str,s._str);
}
return *this;
}String& operator=(const String& s)
{
if(_str != s._str)
{
delete[] _str;
_str = new char[strlen(s._str) + 1];
strcpy(_str,s._str);
}
return *this;
}同时,也考虑到了自己给自己赋值的情况。
可是这样写就完善了吗?是否要再仔细思索一下,还存在问题吗?!其实我可以告诉你,这样的写法也顶多算个初级工程师的写法。前面说过,为了保证内存不泄露,我们前面 delete[] _str,然后我们在把new出来的空间给了_str,但是这样的问题是,你有考虑过
相关文章推荐
- [置顶] 【C++】 双向链表.cpp
- [置顶] 【C++】 单链表 .cpp
- [置顶] 【C++】 复数类操作
- [置顶] 【c语言】 单链表
- [置顶] 【c语言】 单链表
- [置顶] 【C语言】 简易通讯录
- [置顶] 【C语言】 动态开辟二维数组
- [置顶] 【C语言】 使用回调函数实现冒泡排序
- [置顶] 【C语言】 函数指针小谈
- [置顶] 【C语言】 模拟计算器
- [置顶] 【C语言】 浅谈指针
- [置顶] 【C语言】 检测大小端存储
- [置顶] 【C语言】 实现strncpy,strncat,strncmp
- [置顶] 【C语言】 实现memset
- [置顶] 【C语言】 实现memcmp
- [置顶] 【C语言】 实现memmove
- [置顶] 【C语言】 冒泡排序子例
- [置顶] 【C语言】 实现memcpy
- [置顶] 【C语言】 冒泡排序
- [置顶] 【C语言】 实现strcmp