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

移动语义和拷贝语义区别、智能指针

一、移动语义和拷贝语义的区别

1.概念

拷贝语义:

在传统的拷贝操作中,当一个对象被赋值给另一个对象或者作为参数传递给一个函数时,会创建源对象的一个副本。例如,在 C++ 中,如果有一个类MyClass,当执行MyClass obj2 = obj1;(这里obj1是已经存在的MyClass对象),编译器会调用拷贝构造函数来创建obj2,它会复制obj1中的所有成员变量的值。这意味着会有新的内存分配(如果成员变量包含指针,还会复制指针所指向的内容),并且两个对象在内存中有各自独立的存储空间,对obj2的修改不会影响obj1。

移动语义:
移动语义是 C++ 11 引入的一个重要特性。它的目的是避免不必要的拷贝,特别是对于那些拥有资源(如动态分配的内存、文件句柄等)的对象。当使用移动语义时,资源的所有权从一个对象转移到另一个对象,而不是复制资源。例如,对于一个包含动态分配数组的类,移动构造函数可以将源对象中的指针直接赋值给目标对象,然后将源对象中的指针置为nullptr,这样就避免了重新分配内存和复制数组元素的开销。

2.区别: 
资源开销方面

拷贝语义:通常会产生较大的资源开销。如果对象包含大量的数据或者复杂的资源(如大型数组、数据库连接等),拷贝操作可能会消耗大量的时间和内存。例如,一个std::vector对象包含大量元素,当进行拷贝时,需要为新的vector对象分配足够的内存空间,然后逐个复制元素。
移动语义:在移动语义下,资源的转移通常比拷贝快得多。因为它只是简单地改变资源的所有权,而不需要复制资源的内容。继续以std::vector为例,移动构造函数可以简单地将内部指针(指向存储元素的内存块)从源vector转移到目标vector,几乎没有数据复制的开销。
对象状态方面

拷贝语义:源对象和目标对象在拷贝操作后都是有效的,并且它们是相互独立的。源对象的状态在拷贝后保持不变。
移动语义:在移动操作后,源对象通常处于一种 “可析构但可能部分无效” 的状态。例如,一个被移动的std::string对象,它内部的字符数组指针可能被置为nullptr,但对象本身仍然可以被正确地析构(因为析构函数知道如何处理这种情况)。
使用场景方面

拷贝语义:适用于需要独立副本的情况,比如当你想要对一个对象进行修改,但又不希望影响原始对象时,或者当对象的生命周期和作用域要求有独立的副本时。例如,在一个函数中需要对传入的参数进行一些计算,但又不希望改变原始参数的值,就可以使用拷贝语义。
移动语义:在函数返回大型对象或者对象之间转移资源所有权时非常有用。例如,一个函数返回一个动态分配的大型数据结构,使用移动语义可以避免将数据复制一份,从而提高性能。

 二、c++智能指针


在 C++ 中,智能指针是一种用于管理动态分配内存的对象。它们的行为类似于常规指针,但提供了自动内存管理的功能。智能指针的主要目的是帮助防止内存泄漏,因为它们会自动释放所指向的内存,当智能指针对象的生命周期结束时(例如,当它超出作用域时),它所管理的内存会被自动释放。
类型
std::unique_ptr
独占所有权:std::unique_ptr表示独占所有权,即一个对象只能有一个unique_ptr指向它。它不能被复制,但可以被移动。例如:

std::unique_ptr<int> ptr1 = std::make_unique<int>(5);
// 正确的移动操作
std::unique_ptr<int> ptr2 = std::move(ptr1);
// 错误的复制操作
// std::unique_ptr<int> ptr3 = ptr2; 
  • 应用场景:适用于大多数情况下的单一所有者资源管理,比如当一个对象在某个函数或代码块内独占使用一块动态分配的内存时。
  • std::shared_ptr
    • 共享所有权std::shared_ptr实现了共享所有权的语义。多个shared_ptr可以指向同一个对象,并且对象的生命周期会被自动管理,直到最后一个指向它的shared_ptr被销毁。它使用引用计数来跟踪有多少个shared_ptr指向同一个对象。例如:

 

std::shared_ptr<int> ptr3 = std::make_shared<int>(10);
std::shared_ptr<int> ptr4 = ptr3;
  • 应用场景:当多个部分的代码需要共享访问同一个动态分配的对象时,比如在一个复杂的数据结构中,多个节点可能需要共享某些资源,就可以使用shared_ptr
  • std::weak_ptr
    • 弱引用std::weak_ptr是一种弱引用,它通常和shared_ptr一起使用。weak_ptr不会增加所引用对象的引用计数,主要用于解决shared_ptr可能导致的循环引用问题。例如,在一个对象图结构中,两个对象可能通过shared_ptr相互引用,这会导致它们的引用计数永远不会降为 0,从而无法被正确释放。使用weak_ptr可以打破这种循环。

 

 

 


http://www.kler.cn/a/410434.html

相关文章:

  • Leetcode(双指针习题思路总结,持续更新。。。)
  • 使用脚本实现hadoop-yarn-flink自动化部署
  • Leetcode207. 课程表(HOT100)
  • 【计算机网络】网段划分
  • 七天掌握SQL--->第五天:数据库安全与权限管理
  • 整车安全需求考量的多维度深度剖析
  • 深度学习3
  • 论文笔记 网络安全图谱以及溯源算法
  • JavaScript的基础数据类型
  • 241124_基于MindSpore学习Prompt Tuning
  • 【数据分析】基于GEE实现大津算法提取洞庭湖流域水体
  • 手机无法连接服务器1302什么意思?
  • 前端预览pdf文件流
  • 【cocos creator】下拉框
  • Windows系统电脑安装TightVNC服务端结合内网穿透实现异地远程桌面
  • kafka学习-01
  • Unity 2020、2021、2022、2023、6000下载安装
  • 【测试工具JMeter篇】JMeter性能测试入门级教程(一)出炉,测试君请各位收藏了!!!
  • 2024 APMCM亚太数学建模C题 - 宠物行业及相关产业的发展分析和策略 完整参考论文(1)
  • [算法] 前缀函数与KMP算法
  • 数据集-目标检测系列- 荷花 莲花 检测数据集 lotus>> DataBall
  • LeetCode 0632.最小区间:优先队列
  • 成功案例 | Fortinet助力宾堡打造数字化安全“美味王国”
  • java TreeMap 详解
  • 【GAMES101笔记速查——Lecture 19 Cameras,Lenses and Light Fields】
  • C# .Net Core通过StreamLoad向Doris写入CSV数据