当前位置: 首页 > news >正文

c++——浅拷贝和深拷贝、浅赋值和深赋值

目录

一、拷贝构造函数

1.定义

2.按位拷贝

(1)定义

(2)特点

(3)使用场景

二、浅拷贝

1.什么是浅拷贝

2.特点

三、深拷贝(适用于对态资源)

1.什么是深拷贝

2.特点

四、拷贝赋值运算符的深赋值和浅赋值

1.浅赋值

2.深复制

五、总结


一、拷贝构造函数

1.定义

用已有对象来初始化新对象。如果用户没有自定义拷贝构造函数,则系统默认提供一个缺省的拷贝构造函数。

强调:默认的拷贝构造函数是按位拷贝的方式初始化

2.按位拷贝

(1)定义

 是一种对象复制方式,指将一个对象的所有二进制位(bit)原样复制到另一个对象,即逐字节(byte)复制对象在内存中的原始数据。

强调:按位拷贝是编译器默认的拷贝行为,包含默认拷贝构造函数和默认拷贝赋值运算符的实现逻辑。

(2)特点

①不执行任何自定义代码,仅复制内存数据。

②对指针类型,仅复制指针值(地址),不复制指向的内存。

③当对象包含动态资源(比如堆内存)时,会导致多个对象共享同一块内存,调用析构函数后会导致重复释放问题。此时,不合适使用按位拷贝。

(3)使用场景

①对象成员都是基本类型

class Point {
private:int x;  // 基本类型,无动态资源int y;
public:// 编译器生成的默认拷贝构造函数会执行按位拷贝Point(int x_, int y_) : x(x_), y(y_) {}
};int main() {Point p1(10, 20);Point p2 = p1;  // 按位拷贝:复制x=10和y=20,安全有效return 0;
}

②不需要手动释放资源

③对象的指针成员指向全局内存或字符串常量

class ReadOnlyData {
private:const char* str;  // 指向字符串常量(全局资源)
public:ReadOnlyData(const char* s) : str(s) {}
};int main() {ReadOnlyData d1("hello");ReadOnlyData d2 = d1;  // 按位拷贝:d2.str和d1.str指向同一常量,安全return 0;
}

注意:字符串常量存放在数据区,无需手动释放。

二、浅拷贝

根据下面的代码找到运行时出现的问题

class MyString
{
private:char* str;
public:MyString(const char* p = nullptr) :str(nullptr) //构造函数{if (nullptr != p)  //先判断是否为空{int len = strlen(p);//计算字符串的长度str = new char[len + 1];//使用new申请空间——堆区申请空间 (1)sizeof计算大小 (2)malloc (3)构造 (4)返回地址strcpy(str, p);//将p的值拷贝到str中}}~MyString()//析构函数,{if (nullptr != str){delete[] str;str = nullptr;}} void Print() const  //常方法和普通方法都可以进行调用{if (str != nullptr){cout << str << endl;}}
};
int main()
{MyString s1("yhping");MyString s2(s1);//系统自动调用默认拷贝构造函数进行初始化
}

存在的问题:(浅拷贝引起的堆区内存问题)

由于用户没有实现拷贝构造函数,系统默认调用自身的拷贝构造函数,调用后,s1和s2指向同一块内存空间,在调用析构函数时,s3先释放资源,此时,当s1调用析构函数时,会因为多次释放同一块空间,造成程序崩溃。

如图所示:

1.什么是浅拷贝

直接复制对象的所有成员变量值,对于指针类型只复制指针值(地址),不复制指针指向的内存。

2.特点

①多个对象共享同一块动态内存。

②析构时可能导致多次释放同一块内存,引发悬空指针内存泄漏

三、深拷贝(适用于对态资源)

对于上述代码的修改就可以使用深拷贝解决!

1.什么是深拷贝

复制对象的所有成员变量值,对于指针类型,会重新分配内存并复制其指向的内容。

2.特点

①每个对象拥有独立的动态资源副本。

②析构时不会相互影响,避免内存问题。

四、拷贝赋值运算符的深赋值和浅赋值

如果用户没有自定义赋值运算符时,则系统默认提供一个赋值运算符的函数。是一种浅赋值的操作,在语义上等价于按位赋值(逐成员赋值对象)。

如图所示:(默认是浅赋值)

1.浅赋值

(1)定义

赋值时仅复制对象的成员变量值,对于指针类型只复制指针值(地址),不复制指针指向的内存。

(2)特点

  • 多个对象共享同一块动态内存。

  • 赋值后,原对象和目标对象的指针指向同一内存地址。

  • 析构时可能导致多次释放同一块内存,引发悬空指针内存泄漏

2.深复制

对于上述代码造成的问题,可以使用户深赋值解决。

(1)定义

赋值时复制对象的所有成员变量值,对于指针类型,会重新分配内存并复制其指向的内容。

(2)特点

  • 每个对象拥有独立的动态资源副本。

  • 赋值后,原对象和目标对象的指针指向不同内存地址,但内容相同。

  • 析构时不会相互影响,避免内存问题。

五、总结

在类型设计中,使用动态内存或使用内核对象时,必须重新实现拷贝构造函数和赋值重载。(深拷贝、深赋值)。

http://www.lryc.cn/news/585545.html

相关文章:

  • Django快速入门搭建网站
  • 经典同步问题详解
  • 液冷智算数据中心崛起,AI算力联动PC Farm与云智算开拓新蓝海(二)
  • Apache Cloudberry 向量化实践(三)重塑表达式构建路径:Gandiva 优化实战
  • 2D下的几何变换(C#实现,持续更新)
  • SpringBoot或OpenFeign中 Jackson 配置参数名蛇形、小驼峰、大驼峰、自定义命名
  • SpringCloud之Ribbon
  • BootstrapBlazor与JS互调
  • Semi-Supervised Single-View 3D Reconstruction via Prototype Shape Priors
  • 小智AI模型接入MCP
  • 【一起来学AI大模型】微调技术:LoRA(Low-Rank Adaptation) 的实战应用
  • SQL Server通过CLR连接InfluxDB实现异构数据关联查询技术指南
  • SpringBoot JWT
  • Rust与UE5高效集成实战
  • uniapp制作一个个人页面
  • ffmpeg-api记录
  • UC浏览器PC版自2016年后未再更新不支持vue3
  • 小旺AI截图1.2.1版本上线:新增录屏音频、Mac长截屏
  • Docker高级管理--Dockerfile 镜像制作
  • 手把手一起使用Miniforge3+mamba平替Anaconda(Win10)
  • 机器学习week2-线性回归加强
  • Java的extends通配符
  • netdxf—— CAD c#二次开发之(netDxf 处理 DXF 文件)
  • 和鲸社区深度学习基础训练营2025年关卡2(3)pytorch
  • 利用Claude code,只用文字版系统设计大纲,就能轻松实现系统~
  • 免费应用分发平台的安全漏洞和防护机制是什么?
  • 60 美元玩转 Li-Fi —— 开源 OpenVLC 平台入门(附 BeagleBone Black 驱动简单解析)
  • Windows解决 ping 127.0.0.1 一般故障问题
  • 【Linux网络】深入理解HTTP/HTTPS协议:原理、实现与加密机制全面解析
  • 信号量机制