(嵌入式八股)第3章 C++11(二)(后续C++11相关会持续补充在这里)
3.11 移动语义
移动语义 是 C++11 引入的一项重要特性,旨在通过 转移资源所有权 而非 复制资源 来提高程序的性能。它允许对象的资源从一个对象转移到另一个对象,而不是通过传统的深拷贝进行资源复制。移动语义主要解决了拷贝构造和赋值过程中资源重复分配的问题,减少了不必要的内存操作,显著提高了效率。
移动语义的基本概念
移动语义通过 右值引用 来实现。简单来说,移动语义让临时对象或不再需要的对象的资源 "转移" 到另一个对象,而不是复制资源。具体来说,移动构造函数 和 移动赋值运算符 是 C++11 引入的关键特性,它们通过“窃取”源对象的资源来避免冗余的资源分配和释放。
特点:
- 资源转移:资源的所有权从一个对象转移到另一个对象,而不是重新分配和复制。
- 提高性能:特别是在处理动态内存分配、文件句柄等大资源时,避免了拷贝操作,从而提升了程序性能。
移动构造函数(Move Constructor)
移动构造函数 用于创建一个新的对象,并通过 转移 临时对象的资源(即右值引用的资源)来初始化新对象。这避免了不必要的深拷贝操作。
语法:
MyClass&& other
:右值引用,用于接收源对象的资源。noexcept
:表明该函数不会抛出异常,允许编译器进行优化。
原理:
- 移动构造函数将源对象的资源(如指针、内存)“拿走”,并将源对象的资源指针置为
nullptr
,避免源对象在销毁时再次释放这些资源。
obj2
是通过移动构造函数初始化的,obj1
的资源被转移到obj2
,而obj1
的指针被置为nullptr
。
移动赋值运算符(Move Assignment Operator)
移动赋值运算符 用于将一个对象的资源 移动 到另一个已经存在的对象,而不是通过拷贝赋值。它先释放当前对象的资源,然后通过右值引用转移源对象的资源。
语法:
MyClass&& other
:右值引用,用于接收源对象的资源。noexcept
:表明该函数不会抛出异常,允许编译器进行优化。
原理:
- 移动赋值运算符首先释放当前对象的资源,然后将源对象的资源转移到当前对象,并将源对象的资源指针置为
nullptr
,避免重复释放资源。
- 移动赋值运算符将
obj1
的资源转移到obj2
,并释放obj2
原来的资源。
移动语义的优势
- 性能提升:避免了不必要的深拷贝,特别是在处理动态内存、文件句柄、容器等大资源时。
- 资源管理:通过转移资源,避免了资源的重复分配和释放,提高了程序的资源利用率。
- 简化代码:通过移动构造和移动赋值,能够使得临时对象的管理更加高效且清晰,避免了复杂的拷贝构造。
总结
- 移动构造函数:通过右值引用将源对象的资源转移到目标对象,而不是进行拷贝。移动构造函数通常用于临时对象或不再使用的对象的初始化。
- 移动赋值运算符:通过右值引用将资源从一个对象转移到另一个对象,避免了不必要的拷贝操作,释放并管理资源。
- 右值引用(
&&
):是实现移动语义的关键,它允许我们窃取对象的资源而不进行深拷贝。
3.12 完美转发(Perfect Forwarding)
完美转发(Perfect Forwarding)是 C++11 引入的一个非常有用的技术,旨在保持传递参数的 值类别,无论是 左值 还是 右值。它允许函数模板将参数精确地转发到另一个函数中,而不会改变参数的值类别。通过完美转发,可以提高代码的效率,避免不必要的拷贝或移动,并确保参数的原始状态得到保持。
完美转发的目的和作用
完美转发的主要目的是 保持参数的值类别,即无论传递给函数的参数是左值还是右值,函数都能将其转发给下一个函数,同时保持其原始属性。这个特性特别有用,尤其在模板函数或函数模板中,我们希望保持参数的值类别以避免拷贝或错误的资源管理。
在上面的代码中,T&&
是一个“转发引用”,它既可以绑定左值也可以绑定右值。通过 std::forward<T>(arg)
,我们可以将参数 arg
传递给其他函数,同时保留其值类别(左值或右值)。
引用折叠(Reference Collapsing)
引用折叠是实现完美转发的关键机制。它是 C++11 引入的规则,用于将多重引用类型折叠为一个合适的类型。引用折叠的规则决定了当我们使用右值引用参数类型 T&&
时,最终传递的参数类型会根据实际传递的实参的类型进行推导。
引用折叠规则:
- 左值引用的折叠:如果传递的是左值引用类型,T&& 会折叠为 T&。例如:A& && 会折叠成 A&(左值引用折叠)。
- 右值引用的折叠:如果传递的是右值引用类型,T&& 会保持为右值引用类型。例如:A&& && 会折叠成 A&&(右值引用折叠)。
这意味着如果传入左值,T&&
会被折叠为左值引用,传入右值时,T&&
会被保持为右值引用。
x
是左值,因此T&&
被折叠为T&
(即int&
),std::forward<T>(arg)
保持arg
为左值引用。20
是右值,因此T&&
保持为int&&
,std::forward<T>(arg)
保持arg
为右值引用。
std::forward 的作用
std::forward
是 C++11 提供的一个模板函数,用于在完美转发中保持参数的值类别。它通过引用折叠规则判断参数是左值还是右值,并决定是否应将参数转发为左值引用或右值引用。
std::forward
语法:
std::forward<T>(arg)
根据 T
的类型信息判断 arg
是否是左值或右值,并将其转发为相应的值类别。std::forward
只能在 转发 上使用,即参数类型是 (右值引用)。剩余60%内容,订阅专栏后可继续查看/也可单篇购买
作者简介:仅用几个月时间0基础天坑急转嵌入式开发,逆袭成功拿下华为、vivo、小米等15个offer,面试经验100+,收藏20+面经,分享求职历程与学习心得。 专栏内容:这是一份覆盖嵌入式求职过程中99%问题指南,详细讲解了嵌入式开发的学习路径、项目经验分享、简历优化技巧、面试心得及实习经验,从技术面,HR面,AI面,主管面,谈薪一站式服务,助你突破技术瓶颈、打破信息差,争取更多大厂offer。