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中 ...
随机推荐
- xxx,一个神奇的 Python 库
前几天,我在<技术周刊的转变:如何平衡热爱与现实?>一文里写过国内 Python 自媒体圈在近几年的两个现象(仅个人观感,无科学数据支撑): Python 广告投放出现断崖式萎缩 Pyth ...
- NL2SQL技术方案系列(1):NL2API、NL2SQL技术路径选择;LLM选型与Prompt工程技巧,揭秘项目落地优化之道
NL2SQL技术方案系列(1):NL2API.NL2SQL技术路径选择:LLM选型与Prompt工程技巧,揭秘项目落地优化之道 NL2SQL基础系列(1):业界顶尖排行榜.权威测评数据集及LLM大模型 ...
- 【笔记】go语言--字符与字符串处理
[笔记]go语言--字符与字符串处理 rune相当于go的char 使用range遍历pos,rune对(遍历出来是不连续的) 使用utf8.RuneCountInString获得字符数量 使用len ...
- 力扣176(MySQL)-第二高的薪水(中等)
题目: id 是这个表的主键.表的每一行包含员工的工资信息. 编写一个 SQL 查询,获取并返回 Employee 表中第二高的薪水 .如果不存在第二高的薪水,查询应该返回 null . 查询结果如下 ...
- WPF 基于 Azure 的认知服务 情绪分析 语言检测 关键短语提取
本文主要是来安利大家基于 Azure 的认知服务,主要是文本认知服务,可以做到分析输入文本的情绪,以及判断当前输入文本所属语言等功能 本文分为两个部分 ,一个就是在 Azure 上的配置,另一个就是 ...
- 2018-8-10-win10-uwp-如何开始写-uwp-程序
title author date CreateTime categories win10 uwp 如何开始写 uwp 程序 lindexi 2018-08-10 19:16:50 +0800 201 ...
- 4.k8s-配置网络策略 NetworkPolicy
一.基本了解 官方文档:https://kubernetes.io/zh-cn/docs/concepts/services-networking/network-policies/基本了解: 1.网 ...
- 007_Orcad运用Excel表格创建复杂元器件
007_Orcad运用Excel表格创建复杂元器件 以AD9135为例,有88个引脚,如果一个一个输入引脚名,比较慢.用Excel做出引脚列表,比较快捷. 首先需要查询datasheet,用Solid ...
- C语言笔记001-用C语言编写程序
例2-1 在屏幕上显示一个短句"Hello World!". #include <stdio.h> int main(void) { printf("hel ...
- pde复习笔记 第一章 波动方程 第六节 能量不等式、波动方程解的唯一性和稳定性
能量不等式 这一部分需要知道的是能量的表达式 \[E(t)=\int_{0}^{l}u_{t}^{2}+a^{2}u_{x}^{2} dx \] 一般而言题目常见的问法是证明能量是减少的,也就是我们需 ...