移动语义之我见

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

C++11中最晦涩难懂的特性大约就是移动语义了。我最早看到的移动语义是和右值引用一起说的,更有甚者几乎把两者混为一谈。我并不是一个学院派,不敢在此深究二者定义上的区别,但我以为右值引用只是触发移动语义的必要条件而已。
首先谈一谈为什么引入了移动语义,移动语义较以前的拷贝有什么优点?我想先用两个例子来说明这个问题:

class Echo {
public:
    Echo() { std::cout << "new" << std::endl; }
    Echo(const Echo&) { std::cout << "new" << std::endl; }
};

int main(int argc, char** argv) {
    std::vector<Echo> v1, v2;
    v1.resize(5);
    std::cout << v1.size() << " "
              << v2.size() << std::endl;
    v2 = v1;
    std::cout << v1.size() << " "
              << v2.size() << std::endl;
    return 0;
}

运行结果如下:

new
new
new
new
new
5 0
new
new
new
new
new
5 5

main函数修改为如下之后

int main(int argc, char** argv) {
    std::vector<Echo> v1, v2;
    v1.resize(5);
    std::cout << v1.size() << " "
              << v2.size() << std::endl;
    v2 = std::move(v1);
    std::cout << v1.size() << " "
              << v2.size() << std::endl;
    return 0;
}

输出结果为:

new
new
new
new
new
5 0
0 5

不难看出,一段相同功能的代码,使用移动语义大大减少了vector的拷贝次数,从而提升了代码效率。而第二份代码拷贝次数的减少是建立在v1被清空的基础上。所以移动语义的本质其实就是将动态分配的内存的所有权从一个对象转移到另一个对象身上,原来的对象在失去所有权时往往需要将指针设置为空指针,对应到vector对象就意味着size为0。这个过程和auto_ptr的赋值和拷贝几乎一模一样。
明白这上面这点后就很容易理解该在什么时候使用移动语义了。首先一个对象被移动后会失去对动态内存的所有权,一定程度上意味着这个对象不可再用了,因此匿名变量就满足条件,因为匿名变量就是在C++代码中看不到的变量,无法在以后访问它。常见的匿名变量如函数返回值,表达式的值等。或者程序员确定某个有名对象后面不会被使用或者对象会被重置,则可以使用std::move显式地将其转换为右值引用。
或许说到这里依然有很多人对移动语义的作用持怀疑态度,因为我们最一开始给出的例子或许并不常见,又或者很多人都已经习惯了函数参数传引用、返回引用的设计方法,觉得移动语义带来的改变时微乎其微的。那么,请看下面的例子:

class Echo {
public:
    Echo() { std::cout << "new" << std::endl; }
    Echo(const Echo&) { std::cout << "new" << std::endl; }
    Echo& operator=(const Echo&) { std::cout << "=" << std::endl; }
    Echo(Echo&&) { std::cout << "move" << std::endl; }
    Echo& operator=(Echo&&) { std::cout << "move" << std::endl; }
};

int main(int argc, char** argv) {
    Echo a,b;
    std::swap(a, b);
    return 0;
}

这段代码的运行结果为:

new
new
move
move
move

注意最上面的两次new是创建a,b对象打印出来的,这意味引入移动语义可以使swap的不再需要拷贝,而老的C++标准下则需要拷贝三次(因为swap还会用到一个临时变量呢)

注:上面所说的拷贝并不是指Echo对象本身的拷贝,而是指对象所持有的动态内存的拷贝。这里最后强调一遍,移动语义只有对直接或间接(基类或成员)有动态分配的内存的对象才有效果。如果以后代码中出现了类似本文Echo类的移动构造和赋值函数,那就说明还是没懂移动语义。

move移动语义详解 首先引入类别的概念:C++11之前的类别分为左(Lvalue)和(Rvalue),而C++11引入了更细化的分类,包括纯(Prvalue)将亡(Xvalue)和泛左(Glvalue)左:表示一个有持久地址的对象,可以对其取地址。int x = 10;纯:表示一个临时或不占用持久存储的。通常是字面量或计算结果,用于初始化或传递到函数。x + 5;将亡:特殊的,表示即将“被销毁”的对象,可以通过移动语义转移其资源。通常出现在引用和std::move中。 阅读详情

相关推荐

全面理解-c++11中的移动语义

C++11 引入的核心特性,旨在优化资源管理、减少不必要的拷贝开销,尤其是在处理动态内存、文件句柄或大型对象时。其他操作(如读取数据)的行为未定义,需避免使用。:将参数按原类别(左/)传递给其他函数。:函数返回临时对象或传递时,频繁触发拷贝。:直接“窃取”临时对象的资源,避免深拷贝。:将左转换为引用,表示资源可被转移。的资源,并将其置于有效但未定义的状态。:对于包含动态内存或资源的对象(如。避免在移动后访问被移动的对象。:标识可安全转移资源的对象。:仅标记对象为“可移动”。

HL_LOVE_C的博客 1172

C++11新特性 -- 引用移动语义超详解

引用移动语义。 本篇文章会涵盖: 左的区别,怎么去区分左引用的概念,为什么要增加引用引用的作用,解决了什么问题, 引用与左引用的比较,引用的使用场景,引用的注意事项,完美转发的使用,C++11后容器新增的两个默认函数等等

2301_77509762的博客 1712

高级面试:什么是移动语义(Move Semantics)?它是如何提高性能的?

移动语义(Move Semantics)是 C++11 引入的一项重要特性,它允许对象的资源(如堆上分配的内存)在不进行深度复制的情况下进行转移。通过移动语义,可以将对象的资源从一个对象转移到另一个对象,从而避免不必要的内存拷贝,提高程序性能和效率。如何提高性能:减少内存分配和释放的开销:在传统的拷贝语义中,每次对象被复制时都需要进行一次资源的分配和释放,而移动语义可以将资源的所有权从临时对象或对象直接转移到目标对象,避免了额外的内存分配和释放开销。

qiuyehuanghun的博客 2766

引用移动语义

传统的C++语法中就有引用的语法,而C++11中新增了的引用语法特性,所以我们称之前学习的引用为左引用。但无论左引用还是引用,其实都是给对象取别名。

GG_Bruse的博客 8286

C++11引用移动语义

目录 1、基本概念 左 vs 左引用 vs 引用引用 vs 引用 2、引用使用场景和意义 左引用的使用场景 左引用的短板 引用移动语义 ①、移动构造 ②、移动 ③、编译器做的优化 ④、总结 引用引用 引用

bit_zyx的博客 1722

C++11 标准新特性: 引用与转移语义

转自:http://www.ibm.com/developerworks/cn/aix/library/1307_lisl_c11/index.html?ca=dat- 李 胜利, 高级开发工程师, IBM 简介: C++ 的新标准 C++11 已经发布一段时间了。本文介绍了新标准中的一个特性,引用和转移语义。这个特性能够使代码更加简洁高效。 新特性的目的

飞空静渡 3102

移动语义

c++11中引入了移动语义,可以避免无谓的复制,提高程序性能。让我们一起学习“移动语义c++11 测试 临时对象的构造 编译器会自动优化导致有些流程未打印,下面先介绍一下RVO。 RVO(Return Value Optimization)是一种编译器优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象返回,那么这个临时对象会消耗一个构造函数(Constructor)、一...

风一样的男子(quinta)的博客 3993

C++中的移动语义

移动构造函数和移动运算符完成资源转移后,需要将源对象( other )的相关资源指针置空(如 other.data = nullptr )或者重置相关属性(如 other.length = 0 ),以表明资源已经被转移,防止源对象的析构函数错误地释放已经转移的资源。由于这个临时对象是,在初始化 str 对象时,会调用移动构造函数,将 temp 对象中的字符串资源转移到 str 对象中,而不是进行资源复制,提高了效率。在C++中,引用是一种引用类型,用于绑定到。使用引用实现移动语义

2401_88249494的博客 2918

C++移动语义

移动语义其实就是给程序员提供一种触发浅度拷贝的方式, 以避免不必要的深度拷贝;引用特性的引入是支撑移动语义的核心手段引用折叠其实就是在编译器在实例化模板函数参数的时候, 裁剪掉多余的以使语义能正常编译利用引用折叠, T&& t其实可以接收多种类型参数, 使得其成为了万能引用std::move只是单纯的类型转换, 将其他类型或引用类型转换为引用类型std::forward保证了函数参数在函数内部传递给其他函数的时候, 保持类型不变。

lai0yu的博客 1911

一文看懂移动语义

引用,我也不知道为啥突然多出来这么一个让人晦涩难懂的东西,而这个东西的诞生,伴随着C++移动语义的出现。没有,就没有移动语义。二者相辅相成,缺一不可。而移动语义又是现代C++大厦的基石,如果没有理解它,那就没法理解std::thread、std::unique_ptr等等具有独占所有权的类。那么话不多说,让我们来一窥,C++移动语义的神秘面纱。

frankareme的博客 1606

C++移动语义

C++移动语义(Move Semantics)是C++11引入的一个特性,旨在提高程序性能,特别是在对象的临时性和资源管理方面。通过允许“移动”对象,而不是复制对象,移动语义减少了不必要的资源复制,从而提升了效率,尤其是在处理大对象或资源密集型对象时。

qq_52208569的博客 1294

C++ 移动语义

C++ 移动语义特性

zypf_lover的博客 1718

C++:深入理解移动语义

c++进阶之路

weixin_44216359的博客 2415

C++移动语义

C++ 中,移动语义是一种优化机制,允许资源(例如动态分配的内存、文件句柄、数据库连接等)从一个对象 “转移” 到另一个对象,而不是通过复制来共享资源。它通过将对象的内部资源的所有权从一个对象转移到另一个对象,从而避免了不必要的深拷贝,显著提高了性能,尤其在处理大型数据时。移动语义依赖于引用(rvalue references)和移动构造函数移动运算符的支持。通过这些机制,C++ 能够避免昂贵的对象拷贝操作,而是通过“移动”数据的所有权来高效地管理资源。移动语义通过引用移动构造函数。

pumpkin84514的博客 1136

C++11中的移动语义

特性移动语义传统拷贝语义资源处理所有权转移(无深拷贝)深拷贝性能O(1)(高效)O(n)(可能低效)适用场景临时对象、大型资源类、容器操作不可复制资源的小型对象关键字std::move&&noexceptconst&、拷贝构造函数最佳实践为资源管理类实现移动语义。使用std::move显式转移资源。将移动操作标记为noexcept。避免在移动后访问被移动的对象。参考文章:1.透彻理解C++11 移动语义引用、std::move、std::forward2.

weixin_45144862的博客 1218

引用移动语义

它为实现移动语义提供了基础,允许资源的所有权从一个对象“移动”到另一个对象,而不是进行昂贵的复制。C++中的移动语义(Move Semantics)是C++11引入的一种优化技术,旨在提高程序的性能,特别是在涉及大数据量对象时。它通过允许资源(如内存或文件句柄等)从一个对象转移到另一个对象,避免了不必要的深拷贝,从而减少了资源的复制和释放开销。在传统的拷贝语义中,当对象被赋或传递时,通常会执行对象的深拷贝。而移动语义允许将资源的所有权“移动”到新对象,而不是复制内容,避免了不必要的开销。

Bigkinder的博客 2071

C++10中的移动语义

首先,我们来看这样一个函数: (T为一个对象类型)T clone(const T& rhs) { T other = rhs; return other; }这样的函数中,其实会调用两次拷贝构造函数。我们写一个实例看看:class Example { public: Example(); Example(const Example& other); ~Exa

给永远比拿愉快 3560
上一篇: 欢迎使用CSDN-markdown编辑器
下一篇: 线程池中使用条件变量和信号量的性能比较
Kylin_he
博客等级 码龄16年 10粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值