当前位置:首页 » 《关注互联网》 » 正文

【C++拓展】深拷贝的传统写法vs现代写法,你更喜欢哪个?

29 人参与  2024年11月23日 12:01  分类 : 《关注互联网》  评论

点击全文阅读


        这篇呢是关于深拷贝的拓展知识。目前我们学到的知识中,会用到深拷贝就是拷贝构造赋值运算符重载。传统写法的代码实现相信大家已经是手拿把掐,知道现代写法如何实现吗?我们来一起看看。(全文以我们前面模拟实现的string类为背景,文中函数的返回值类型最好是string的引用)

1.拷贝构造和operator=的传统写法

用已经存在的对象去初始化另一个刚创建的对象,此时调用拷贝构造。

string s1("hello world");string s2 = s1;//此时调用拷贝构造//s2(s1)和s2 = s1一个意思,写法不同而已
string(const string& s)//拷贝构造传统写法{_str = new char[s._capacity + 1]; //s2开和s1一样的大小strcpy(_str, s._str);//拷贝数据_size = s._size;_capacity = s._capacity;}

两个已经存在的对象之间的拷贝复制,就调用operator=赋值运算符重载。

string s1("hello world");string s2("xxxxxxxx");s2 = s1;//s1,s2都已经存在,此时是赋值
string operator=(const string& s) //传统赋值重载{if (this != &s) //不是自己给自己赋值时{delete[] _str; //释放原来空间_str = new char[s._capacity + 1];_size = s._size;_capacity = s._capacity;}return *this;}

传统写法呢就是我们自己开空间,自己拷贝数据,现代写法就是我们让“别人”帮我们开空间,帮我们拷贝数据。

 2.拷贝构造现代写法

先看代码再解释。这里s就是s1,隐形的this指针就是s2。

//拷贝构造s2(s1)string(const string& s)//拷贝构造现代写法{string temp(s._str);swap(_str, temp._str);swap(_size, temp._size);swap(_capacity, temp._capacity);}

s2想和s1有一样大的空间,一样的值,我们不自己处理这些事,让temp来处理,temp处理好了,s2和temp一交换。

这样处理的前提是,我们在成员函数声明的地方给了缺省值,不然会对随机值释放,如下。

private:char* _str = nullptr;size_t _size = 0;size_t _capacity = 0;

是不可以对随机值释放的,相当于释放的野指针,这里要注意一下。

这里的交换呢,我们还可以单独写一个交换函数。

void swap(string& s){//调用算法库里面的swap函数std::swap(_str, s._str);std::swap(_size, s._size);std::swap(_capacity, s._capacity);}

然后再调用这个自己写的swap函数。

//s2(s1)string(const string& s)//拷贝构造现代写法{string temp(s._str);swap(temp);}

 看到这里我相信你一定有很多疑惑,不着急,存在即合理,我慢慢解释,来画图分析。

开始的时候s2是指向nullptr,因为我们前面给的缺省值是nullptr。

然后我们构造了一个temp对象,temp里面存和s1一样的内容。

此时temp里面的内容就是s2想要的,this就是s2,然后s2和temp交换。

temp出了作用域就销毁了,此时temp是nullptr,这里会调用析构函数,可以释放空,所以前面我们才强调要给缺省值。

此时s2就和s1一样大,而且内容也一样。但是这个活是“别人”干的,是temp干的,然后s2通过交换,掠夺“别人”的“成果”。

3.operator=的现代写法

赋值也可以用和拷贝构造类似的写法。

//赋值s2 = s1;string operator=(const string& s)//赋值重载现代写法{if (this != &s) //不是自己给自己赋值时{string temp(s._str);swap(temp);}return *this;}

s2想和s1有一样大的空间,一样的值,还是一样,我们不自己处理这些事,让temp来处理。

 我们构造了一个temp对象,temp里面存和s1一样的内容。

此时temp里面的内容就是s2想要的,this就是s2,然后s2和temp交换。

 temp出了作用域就销毁了,此时temp是"xxxxxxxx",这里会调用析构函数。

最后返回*this,就是"hello world"。此时s2就和s1一样大,而且内容也一样。

从图的分析可以看出,我们不仅掠夺了temp的成果,还让temp把s2原来的空间给释放了,在传统写法中我们首先要释放s2的旧空间,现在我们都不用自己释放了。

传统写法就是我们自己完成所有步骤,现代写法就是让“别人”帮我们完成。

4.operator=现代写法的再变形

//赋值重载s2 = s1;string operator=(string s){swap(s);return *this;}

参数列表不再引用传参,因为这个代码下引用传参会改变s1。

this直接和s交换。 

 然后返回*this,出作用域s销毁。

传统写法和现代写法你更喜欢哪个呢?我们以后也会用到现代写法的,就介绍到这里了,拜拜~


点击全文阅读


本文链接:http://zhangshiyu.com/post/190751.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1