(嵌入式八股)第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&& 时,最终传递的参数类型会根据实际传递的实参的类型进行推导。

引用折叠规则:

  1. 左值引用的折叠:如果传递的是左值引用类型,T&& 会折叠为 T&。例如:A& && 会折叠成 A&(左值引用折叠)。
  2. 右值引用的折叠:如果传递的是右值引用类型,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。

    全部评论

    相关推荐

    Ncsbbss:又想干活又想要工资,怎么什么好事都让你占了
    点赞 评论 收藏
    分享
    04-14 20:10
    已编辑
    门头沟学院 Java
    点赞 评论 收藏
    分享
    评论
    5
    7
    分享

    创作者周榜

    更多
    牛客网
    牛客企业服务