深浅拷贝——string-创新互联
对于一般的对象,如:
十余年的西峰网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。网络营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整西峰建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联公司从事“西峰网站设计”,“西峰网站推广”以来,每个客户项目都认真落实执行。int a = b;
int c = 5;
它们之间的赋值,复制很简单,到对于类对象来说,其内部存在各种成员变量,他的复制,赋值就不是如此的简单,如果处理不当,就会出现各种问题。
我们首先来看一下下面的代码:
#include
using namespace std;
#include
class String
{
public:
String(const char* ptr)
:_ptr(new char[strlen(ptr) + 1])
{
strcpy(_ptr, ptr);
cout << "String" << endl;
cout << _ptr << endl;
}
String(const String& ptr)
:_ptr(ptr._ptr)
{}
String& operator=(const String& ptr)
{
if (this != &ptr)
{
_ptr = ptr._ptr;
}
return *this;
}
~String()
{
cout << "~String" << endl;
delete[] _ptr;
}
private:
char * _ptr;
};
void Test()
{
String s("hello");
String s2(s);
}
int main()
{
Test();
return 0;
}
可以看到,这里对同一对象析构了两次,我们通过下面的图来对这个现象进行解释:
在进行对象复制后,事实上s、s2里的成员指针_ptr都指向了一块内存空间(即内存空间共享了),在s1析构时,delete了成员指针_ptr所指向的内存空间,而s2析构时同样指向(此时已变成野指针)并且要释放这片已经被s1析构函数释放的内存空间,这就让同样一片内存空间释放了两次 ,从而出错。而浅拷贝还存在着一个问题,因为一片空间被两个不同的子对象共享了,只要其中的一个子对象改变了其中的值,那另一个对象的值也跟着改变了。
在这里呢我们找到了深拷贝来解决这个问题。
下面是深拷贝的拷贝构造函数代码:
String(const String& ptr)
:_ptr(new char[strlen(ptr._ptr) + 1])
{
strcpy(_ptr, ptr._ptr);
}
这里通过重新开辟一段空间来解决浅拷贝中析构两次的情况。
在浅拷贝中还存在其他的一些问题,比如赋值运算符重载,他也是s,s1,两个对象指向同一块内存空间。在析构时同样会出现问题。还有析构函数,如果这块空间为NULL,又怎么能进行析构呢!
我们给出深拷贝的函数代码:
class String
{
public:
String(const char* ptr)
:_ptr(new char[strlen(ptr) + 1])
{
strcpy(_ptr, ptr);
}
String(const String& ptr)
:_ptr(new char[strlen(ptr._ptr) + 1])
{
strcpy(_ptr, ptr._ptr);
}
String& operator=(const String& ptr)
{
if (this != &ptr)
{
delete[] _ptr;
char* tmp = new char[strlen(ptr._ptr) + 1];
strcpy(tmp, ptr._ptr);
_ptr = tmp;
}
return *this;
}
~String()
{
if (_ptr)
{
delete[] _ptr;
}
}
private:
char* _ptr;
};
void Test()
{
String s("hello");
String s2(s);
String s3("11111");
s3 = s;
}
int main()
{
Test();
return 0;
}
通过深拷贝我们就能解决浅拷贝的问题。
对深拷贝中的赋值运算符重载我们做以下说明:
1.进入赋值运算符重载,我们首先需要判断该对象是不是自己给自己赋值,自己给自己赋值从赋值上来说也没错,但是在调用析构函数时又怎该去析构呢?不是又给同一对象析构两次吗?
2.赋值运算符重载的深层理解
String& operator=(const String& ptr)
s3 = s;
赋值运算符重载传参是其实是这样的:s3.operator=(&s3,s),&s3其实就是this指针,在实现赋值运算符重载的过程中,首先析构掉s3原本空间的内容,然后开辟一段新空间,把s的内容复制到新空间中,再把新空间的内容给给s3,完成赋值。
另外有需要云服务器可以了解下创新互联scvps.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。
网站名称:深浅拷贝——string-创新互联
网站地址:http://ybzwz.com/article/dsipgd.html