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)浅拷贝和深拷贝的更多相关文章

  1. Python day4_list的常见方法1_笔记(浅拷贝和深拷贝的简述)

    li=[1,2,3,'55dd'] li.clear()#清除列表内容 print(li) li.append(1)#追加 li.append(3) print(li) #拓展:直接赋值和copy和d ...

  2. 我的Python学习笔记(二):浅拷贝和深拷贝

    在Python中,对象赋值,拷贝(浅拷贝和深拷贝)之间是有差异的,我们通过下列代码来介绍其区别 一.对象赋值 对象赋值不会复制对象,它只会复制一个对象引用,不会开辟新的内存空间 如下例所示,将test ...

  3. 流畅的python学习笔记第八章:深拷贝,浅拷贝,可变参数

    首先来看赋值,浅拷贝,深拷贝. 一赋值: a=['word',2,3] b=a print id(a),id(b) print [id(x) for x in a] print [id(x) for ...

  4. Python3.5-20190504-自我笔记浅拷贝和深拷贝

    浅拷贝和深拷贝 (自己一直搞不懂的) 1.直接赋值(把一个变量直接赋值给另一个变量),他们指向同一个内存的数据(右边的图不知道怎么画,就直接截图过来了.将就看看) ------------- 2.使用 ...

  5. [编程基础] Python对象的浅拷贝与深拷贝笔记

    Python中的赋值语句不创建对象的副本,它们只将名称绑定到对象.对于不可变的对象,这通常没有什么区别.但是对于处理可变对象或可变对象的集合,您可能需要寻找一种方法来创建这些对象的"真实副本 ...

  6. c#中浅拷贝和深拷贝的理解

    c#中拷贝有浅拷贝和深拷贝之分. 例如对象A,其中有值类型字段和引用类型字段: 1.浅拷贝: 对于值类型字段,直接逐位复制到新拷贝的副本对象中,修改副本的字段的值,不会影响源对象中字段的值: 对于引用 ...

  7. C#浅拷贝与深拷贝区别

    也许会有人这样解释C# 中浅拷贝与深拷贝区别: 浅拷贝是对引用类型拷贝地址,对值类型直接进行拷贝. 不能说它完全错误,但至少还不够严谨.比如:string 类型咋说? 其实,我们可以通过实践来寻找答案 ...

  8. javascript 关于赋值、浅拷贝、深拷贝的个人理解

    关于赋值.浅拷贝.深拷贝,以前也思考良久,很多时候都以为记住了,但是,我太难了.今天我特地写下笔记,希望可以完全掌握这个东西,也希望可以帮助到任何想对学习这个东西的同学. 一.栈.堆.指针地址 栈内存 ...

  9. [转] js对象浅拷贝和深拷贝详解

    本文为大家分享了JavaScript对象的浅拷贝和深拷贝代码,供大家参考,具体内容如下 1.浅拷贝 拷贝就是把父对像的属性,全部拷贝给子对象. 下面这个函数,就是在做拷贝: var Chinese = ...

  10. 【转】Python中的赋值、浅拷贝、深拷贝介绍

    这篇文章主要介绍了Python中的赋值.浅拷贝.深拷贝介绍,Python中也分为简单赋值.浅拷贝.深拷贝这几种"拷贝"方式,需要的朋友可以参考下   和很多语言一样,Python中 ...

随机推荐

  1. 重新整理 .net core 实践篇—————微服务的桥梁EventBus[三十一]

    前言 简单介绍一下EventBus. 正文 EventBus 也就是集成事件,用于服务与服务之间的通信. 比如说我们的订单处理事件,当订单处理完毕后,我们如果通过api马上去调用后续接口. 比如说订单 ...

  2. 力扣233(java)-数字1的个数(困难)

    题目: 给定一个整数 n,计算所有小于等于 n 的非负整数中数字 1 出现的个数. 示例 1: 输入:n = 13输出:6示例 2: 输入:n = 0输出:0 提示: 0 <= n <= ...

  3. ATC'22顶会论文RunD:高密高并发的轻量级 Serverless 安全容器运行时 | 龙蜥技术

    简介: RunD可以在88毫秒内启动,并且在104核384GB内存的单节点上每秒启动超过200个安全容器. 编者按:目前的安全容器软件栈 - 包括 host 操作系统中的 cgroup.guest 操 ...

  4. PolarDB 并行查询的前世今生

    简介:本文会深入介绍PolarDB MySQL在并行查询这一企业级查询加速特性上做的技术探索.形态演进和相关组件的实现原理,所涉及功能随PolarDB MySQL 8.0.2版本上线. ​ 作者 | ...

  5. Spring Boot参数校验以及分组校验的使用

    简介: 做web开发基本上每个接口都要对参数进行校验,如果参数比较少,还比较容易处理,一但参数比较多了的话代码中就会出现大量的if-else语句.虽然这种方式简单直接,但会大大降低开发效率和代码可读性 ...

  6. 运营也用的起来的数据分析工具:Quick BI即席分析详解

    ​简介: 数据部门是一个容易被投诉的"高危"部门,需求响应慢.数据准确性不高会影响业务的发展. 然而数据分析师每周动辄就有几十个需求在手,无限的加班也无法解决所有问题,到底怎样才能 ...

  7. 一键入门到精通:sd-webui-prompt-all-in-one 项目大揭秘!

    今天向大家推荐一个宝藏项目.在创意无限的AI艺术生成世界中,sd-webui-prompt-all-in-one 项目如一股清流,为广大创作者和开发者带来了前所未有的便捷和灵感.这不仅仅是一个项目,它 ...

  8. FFmpeg开发笔记(十八)FFmpeg兼容各种音频格式的播放

    ​FFmpeg结合SDL可以播放音频文件,也能播放视频文件中的音频流,<FFmpeg开发实战:从零基础到短视频上线>一书第10章的示例程序playaudio.c支持播放mp3和aac两种格 ...

  9. 11.IO 流

    1.IO 流引入 概述:以应用程序为参照物,读取数据为输入流(Input),写数据为输出流(Output),大量输入输出数据简称 IO 流 原理: 2.IO 流的分类 读写的文件分类 二进制文件:打开 ...

  10. 鸿蒙HarmonyOS实战-ArkUI事件(焦点事件)

    前言 焦点事件是指程序中的重要事件或关键点.焦点事件通常是程序的核心逻辑和功能,需要引起特殊的关注和处理. 在图形用户界面(GUI)编程中,焦点事件通常与用户交互和界面输入相关.例如,当用户点击按钮. ...