C++中的浅拷贝与深拷贝
来源:互联网 发布:淘宝扩容128g u盘判断 编辑:程序博客网 时间:2024/06/15 10:28
用自定义的String类解释什么是浅拷贝什么是深拷贝。
class String { private: char* _str; };浅拷贝是在调用拷贝函数时进行了值拷贝,这样的拷贝看似没有问题,在调用析构函数时会导致内存泄漏,系统奔溃。
#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;class String{public:String(const char*str=""):_str(new char[strlen(str) + 1]){strcpy(_str, str);cout << "String" << endl;}~String(){if (_str){delete[]_str;cout << "~String" << endl;}}char *Getstr(){return _str;}private:char*_str;};void TestString(){String s1("hello world!");String s2;String s3(s1);//String s2 = s1;cout << s1.Getstr() << endl;cout << s3.Getstr() << endl;}int main(){TestString();system("pause");return 0;}我们自己编写了构造函数和析构函数,在运行测试用例时出现系统奔溃:
是因为在String s3(s1)时系统调用默认拷贝构造即“浅拷贝”。
所以我们要自己编写拷贝构造与赋值运算符重载,进行深拷贝。
深拷贝是指在拷贝构造时,新开辟一块空间,将_str指向的内容拷贝到这块新的空间里,再将自己的_str指向这块空间。下面是代码:
#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;class String{public:String(const char*str=""):_str(new char[strlen(str) + 1]){strcpy(_str, str);cout << "String" << endl;}~String(){if (_str){delete[]_str;cout << "~String" << endl;}}String(const String& d){this->_str = new char[strlen(d._str) + 1]; //this可以省略,+1是因为字符串后还有‘\0’strcpy(_str, d._str);}String& operator=(const String& d){if (this != &d){delete[]_str; //首先释放自己空间_str = new char[strlen(d._str) + 1];strcpy(_str, d._str);}return *this;}char *Getstr(){return _str;}private:char*_str;};void TestString(){String s1("hello world!");String s2;String s3(s1); s2 = s1;cout << s1.Getstr() << endl;cout << s3.Getstr() << endl;cout << s2.Getstr() << endl;}
运行结果为:
还有一种是现代写法,相对于传统写法更简洁一点,是让别人开空间拷贝字符串,再将别人的空间与自己交换,坐享渔翁之利。
代码如下:
#define _CRT_SECURE_NO_WARNINGS 1#include<iostream>using namespace std;class String{public:String(const char*str=""):_str(new char[strlen(str) + 1]){strcpy(_str, str);cout << "String" << endl;}~String(){if (_str){delete[]_str;cout << "~String" << endl;}}String(const String& d):_str(NULL) //如果tmp置空可以避免释放野指针 {String tmp(d._str); //让临时对象tmp去构造与d._str相同的空间,再将tmp与自己交换swap(_str, tmp._str);}String& operator=(const String& d){if (this != &d){String tmp(d._str); //赋值首先要做的是释放自己的空间,然后创建一块新空间,赋值为其他对象成员变量swap(_str, tmp._str); //现代写法可以减少释放自己空间这一步骤,因为临时对象tmp在函数调用后自动释放}return *this;}char *Getstr(){return _str;}private:char*_str;};void TestString(){String s1("hello world!");String s2;String s3(s1); s2 = s1;cout << s1.Getstr() << endl;cout << s3.Getstr() << endl;cout << s2.Getstr() << endl;}int main(){TestString();system("pause");return 0;}现代写法中的赋值运算符重载也可以使用对象参数,上面使用的是引用。
String& operator=(String s){swap(_str, s._str);return *this;}在这种写法中,因为参数是一个临时变量,所以在调用赋值函数时String s就是对象的临时拷贝,可以直接交换,
String s因为是临时变量,在出了作用域后自动销毁,不用自己调用delete函数。
阅读全文
0 0
- C中的深拷贝和浅拷贝
- c++中的深拷贝与浅拷贝
- C#中的浅拷贝与深拷贝
- C#中的深拷贝与浅拷贝
- Python中的浅拷贝与深拷贝
- java中的深拷贝与浅拷贝
- IOS中的深拷贝与浅拷贝
- python中的深拷贝与浅拷贝
- Java中的浅拷贝与深拷贝
- c++中的浅拷贝与深拷贝
- java 中的深拷贝与浅拷贝
- C++中的深拷贝与浅拷贝
- Javascript中的深拷贝与浅拷贝
- java中的深拷贝与浅拷贝
- Java中的深拷贝与浅拷贝
- Java中的浅拷贝与深拷贝
- iOS中的深拷贝与浅拷贝
- C++中的浅拷贝与深拷贝
- TCP的四种定时器
- Linux下 wchar_t 与char 转换
- Python学习01 — 随机生成10个大写、小写字母、特殊字符
- 0513学习总结(数据结构,链表)
- 谁能解释百度翻译上的一个语法问题
- C++中的浅拷贝与深拷贝
- Sqlite3数据库
- 一文弄懂神经网络中的反向传播法——BackPropagation
- 0514学习总结(双链表)
- HTTP请求与响应基础
- HTML表单输入类型总结
- iOS中UITextField不弹起输入键盘,弹起自定义的菜单
- 双向绑定----通过监听方式配合处理器方法实现
- 0520学习总结(栈,链栈,队列)