当前位置: 首页 > 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.dtcms.com/a/274551.html

相关文章:

  • 动态组件和插槽
  • mysql 锁介绍
  • 分布式系统高可用性设计-负载均衡与容错机制深度解析
  • 2025年DevSecOps工具全景图:安全左移时代的国产化突围
  • AGX Xavier 搭建360环视教程【二、环境配置】
  • 【JMeter】执行系统命令
  • git restore
  • Java项目中图片加载路径问题解析
  • 多线程Java
  • Leaflet面试题及答案(1-20)
  • 《汇编语言:基于X86处理器》第7章 整数运算(2)
  • Ubuntu 22.04 Server 虚拟机初始化配置与优化指南
  • 用Python制作抖音风格短视频:从图片到精美视频的完整指南
  • docker-compose安装常用中间件
  • AI产品经理面试宝典第7天:核心算法面试题-上
  • VS 按F12 提示cannot navigate to the symbol under the caret
  • JavaSE——Object
  • 【实时Linux实战系列】现有应用迁移到实时环境的步骤
  • Web安全-Linux基础-01-初识Linux
  • 进程状态 + 进程优先级切换调度-进程概念(5)
  • 小智AI模型接入MCP
  • 【C++】内联函数inline以及 C++入门(4)
  • 【Linux】C++项目分层架构:核心三层与关键辅助
  • 构建一个简单的有监督的异常点检测项目
  • 如何让FastAPI与Celery完美联姻,打造高效异步任务处理系统?
  • 灰盒级SOA测试工具Parasoft SOAtest重新定义端到端测试
  • uniapp制作一个视频播放页面
  • 软件测试之单元测试
  • 【Luogu】每日一题——Day1. P3385 【模板】负环
  • 功能测试知识总结