温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

深浅拷贝——string

发布时间:2020-07-11 18:21:05 来源:网络 阅读:518 作者:I慕蓝 栏目:编程语言

对于一般的对象,如:

int a = b;

int c = 5;

它们之间的赋值,复制很简单,到对于类对象来说,其内部存在各种成员变量,他的复制,赋值就不是如此的简单,如果处理不当,就会出现各种问题。

我们首先来看一下下面的代码:

#include<iostream>

using namespace std;

#include<string.h>

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;

}

深浅拷贝——string

可以看到,这里对同一对象析构了两次,我们通过下面的图来对这个现象进行解释:

深浅拷贝——string

在进行对象复制后,事实上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,完成赋值。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI