C++笔记(5)浅拷贝和深拷贝
2023-02-18 16:27:15 时间
1. 定义
浅拷贝(shallow copy):多个对象共用同一块资源,同一块资源释放多次,崩溃或者内存泄漏
深拷贝(deep copy):每个对象共同拥有自己的资源,必须显式提供拷贝构造函数和赋值运算符。
2. 示例
(书p355)
#include <iostream> using namespace std; //类声明 class String { private: char* str; int len; static int num_strings; public: String(const char* s); String(); ~String(); friend std::ostream& operator<<(std::ostream& os, const String& s); }; //不能在类声明中初始化静态成员变量 int String::num_strings = 0; String::String(const char* s) { len = strlen(s); str = new char[len + 1]; strcpy_s(str, strlen(s) + 1, s); num_strings++; cout << "num_strings:\"" << str << "\"object created\n"; } //类实现 String::String() { len = 4; str = new char[len + 1]; strcpy_s(str, 4, "c++"); num_strings++; cout << "num_strings:\"" << str << "\"object created\n"; } String::~String() { cout << "num_strings:\"" << str << "\"object deleted\n"; num_strings--; cout << num_strings << " object left\n"; delete[] str; } std::ostream& operator<<(std::ostream& os, const String& s) { os << s.str << ":" << int(s.str) << endl; return os; } //主函数 int main() { { String s1 = "aaaa"; cout << s1; String s2 = s1; cout << s2; } cout << "End of main()!\n"; return 0; }
运行中断:
num_strings:"aaaa"object created aaaa:16857352 aaaa:16857352 num_strings:"aaaa"object deleted 0 object left num_strings:"葺葺葺葺葺葺葺葺?b@?"object deleted -1 object left
默认的拷贝构造函数逐个复制非静态成员(浅拷贝),复制的是成员的值。
String s2 = s1;
相当于:
String s2; s2.str = s1.str; s2.len=s1.len;
其中,s2.str = s1.str复制的不是字符串,而是指向字符串的指针。也就是说,将s2初始化为是s1后,得到两个指针指向一个字符串。析构函数释放了s2.str指针指向的内存,因此在释放s2时,导致了不确定,可能有害的结果。
解决这类设计中这种问题的方法是进行深拷贝(deep copy)。也就是说,拷贝构造函数应该复制字符串并将副本的地址赋给str成员,而不仅仅是复制字符串地址。这样每个对象都有自己的字符串,而不会试图去释放已经被释放的字符串。
可以定义一个显式拷贝构造函数以解决问题:
String::String(const String& st) { len = st.len; str = new char[len + 1]; strcpy_s(str, len+1, st.str); num_strings++; cout << "num_strings:\"" << str << "\"object created\n"; }
运行结果:
num_strings:"aaaa"object created num_strings:"aaaa"object created num_strings:"aaaa"object deleted 1 object left num_strings:"aaaa"object deleted 0 object left
End of main()!
3. 总结
如果类中包含了使用new初始化的指针成员,应当定义一个拷贝构造函数,以复制指向的数据,而不是指针。
相关文章
- 数据结构:7种哈希散列算法,你知道几个?
- IDEA Plugin,写一个看股票指数和K线的插件
- 12种 vo2dto 方法,就 BeanUtils.copyProperties 压测最拉胯!【快双11了,别用错喽】
- 以一己之力,生抗美团技术博客!
- 谁说明天上线,这货压根不知道开发流程!
- 2020总结 | 作为技术号主的一年!
- 阿里不允许使用 Executors 创建线程池!那怎么使用,怎么监控?
- 手写线程池,对照学习ThreadPoolExecutor线程池实现原理!
- 数据源太多,报表工具该如何兼容?
- 如何集成开源图表及报表到自研项目中
- 数据批处理速度慢?不妨试试这个
- etcd v3版本生产级集群搭建以及实现一键启动脚本
- 长篇图解etcd核心应用场景及编码实战
- [PostgreSql]生产级别数据库安装要考虑哪些问题?
- 用了这跨操作系统远控软件,我再也不出差了
- spring接口多实现类,该依赖注入哪一个?
- 延时任务-基于redis zset的完整实现
- 延时任务-基于netty时间轮算法实现
- 完整实现-通过DelayQueue实现延时任务
- 数据分表Mybatis Plus动态表名最优方案的探索