C++笔记(5)浅拷贝和深拷贝
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初始化的指针成员,应当定义一个拷贝构造函数,以复制指向的数据,而不是指针。
C++笔记(5)浅拷贝和深拷贝的更多相关文章
- Python day4_list的常见方法1_笔记(浅拷贝和深拷贝的简述)
li=[1,2,3,'55dd'] li.clear()#清除列表内容 print(li) li.append(1)#追加 li.append(3) print(li) #拓展:直接赋值和copy和d ...
- 我的Python学习笔记(二):浅拷贝和深拷贝
在Python中,对象赋值,拷贝(浅拷贝和深拷贝)之间是有差异的,我们通过下列代码来介绍其区别 一.对象赋值 对象赋值不会复制对象,它只会复制一个对象引用,不会开辟新的内存空间 如下例所示,将test ...
- 流畅的python学习笔记第八章:深拷贝,浅拷贝,可变参数
首先来看赋值,浅拷贝,深拷贝. 一赋值: a=['word',2,3] b=a print id(a),id(b) print [id(x) for x in a] print [id(x) for ...
- Python3.5-20190504-自我笔记浅拷贝和深拷贝
浅拷贝和深拷贝 (自己一直搞不懂的) 1.直接赋值(把一个变量直接赋值给另一个变量),他们指向同一个内存的数据(右边的图不知道怎么画,就直接截图过来了.将就看看) ------------- 2.使用 ...
- [编程基础] Python对象的浅拷贝与深拷贝笔记
Python中的赋值语句不创建对象的副本,它们只将名称绑定到对象.对于不可变的对象,这通常没有什么区别.但是对于处理可变对象或可变对象的集合,您可能需要寻找一种方法来创建这些对象的"真实副本 ...
- c#中浅拷贝和深拷贝的理解
c#中拷贝有浅拷贝和深拷贝之分. 例如对象A,其中有值类型字段和引用类型字段: 1.浅拷贝: 对于值类型字段,直接逐位复制到新拷贝的副本对象中,修改副本的字段的值,不会影响源对象中字段的值: 对于引用 ...
- C#浅拷贝与深拷贝区别
也许会有人这样解释C# 中浅拷贝与深拷贝区别: 浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝. 不能说它完全错误,但至少还不够严谨.比如:string 类型咋说? 其实,我们可以通过实践来寻找答案 ...
- javascript 关于赋值、浅拷贝、深拷贝的个人理解
关于赋值.浅拷贝.深拷贝,以前也思考良久,很多时候都以为记住了,但是,我太难了.今天我特地写下笔记,希望可以完全掌握这个东西,也希望可以帮助到任何想对学习这个东西的同学. 一.栈.堆.指针地址 栈内存 ...
- [转] js对象浅拷贝和深拷贝详解
本文为大家分享了JavaScript对象的浅拷贝和深拷贝代码,供大家参考,具体内容如下 1.浅拷贝 拷贝就是把父对像的属性,全部拷贝给子对象. 下面这个函数,就是在做拷贝: var Chinese = ...
- 【转】Python中的赋值、浅拷贝、深拷贝介绍
这篇文章主要介绍了Python中的赋值.浅拷贝.深拷贝介绍,Python中也分为简单赋值.浅拷贝.深拷贝这几种"拷贝"方式,需要的朋友可以参考下 和很多语言一样,Python中 ...
随机推荐
- 深入探讨下SSR与CSR有啥不同
随着互联网技术的迅速发展,用户对网页的加载速度和交互体验有了更高的期待.作为开发者,我们常常需要在服务器端渲染(SSR)与客户端渲染(CSR)之间做出选择.这两种渲染方式各有特点,适用于不同的场景和需 ...
- Flink Standalone集群jobmanagers高可用配置
上篇文章简单叙述了Flink standalone集群的基础部署,在生产环境中假如只有1个jobmanager的话,那么这个节点一旦挂掉,所有运行的task都会中断,带来的影响比较大,因此在生产环境至 ...
- 关于<property name="hibernate.hbm2ddl.auto"></property>中的参数填写
hibernate的数据库表自动生成参数 关于<property name="hibernate.hbm2ddl.auto"></property>中的参数 ...
- 亿图version 9.2安装教程
记录一下自己安装亿图9.2版本的安装过程~ 先获取安装资料: 百度网盘链接: 链接:https://pan.baidu.com/s/1zJDcF9Y0Xy2CvD4mG_oOfQ?pwd=pqy9 提 ...
- Serverless 可观测性的过去、现在与未来
简介: 函数计算可观测性经历了 1.0 -> 2.0 的发展,从闭门造车的可观测发展成开源的可观测,从平台的可观测发展为开发者的可观测,从FaaS Only 的可观测演进成了云原生的可观测. 作 ...
- 如何避免JS内存泄漏?
简介: 很多开发者可能平时并不关心自己维护的页面是否存在内存泄漏,原因可能是刚开始简单的页面内存泄漏的速度很缓慢,在造成严重卡顿之前可能就被用户刷新了,问题也就被隐藏了,但是随着页面越来越复杂,尤 ...
- [FE] G2Plot 更新图表的两种方式
第一种是使用 G2Plot 对象上的 changeData 方法,如果不涉及到全局 title 等这些的更改,可以采用这种方式. 也就是说,只有纯数据方面的变动,使用 changeData 更新图表数 ...
- dotnet 性能优化 利用哈希思想优化大对象集合相等判断性能
利用哈希的其中一个思想,相同的对象的哈希值相同,可以用来提升一些大对象集合的进行对象相等判断的性能.大对象的相等判断指的是有某些类型的相等判断需要用到对象的很多属性或字段进行参与判断逻辑才能判断两个对 ...
- WPF 笔迹触摸点收集工具
本文来安利大家一个工具,可以用来收集笔迹的触摸点,这个工具完全开源 在开始之前先看一下工具的界面 实现方式其实就在触摸的时候收集触摸点信息,上面的工具有很多功能都没有实现的.笔迹绘制的功能使用 WPF ...
- 2019-8-31-C#-大端小端转换
title author date CreateTime categories C# 大端小端转换 lindexi 2019-08-31 16:55:58 +0800 2018-05-28 10:21 ...