【问题标题】:What has changed in C++17 in terms of MOVE elisionC++17 在 MOVE 省略方面发生了什么变化
【发布时间】:2021-12-01 22:26:46
【问题描述】:

C++17 中是否保证了“移动省略”?让我解释一下我的意思。在几乎每一篇关于 C++17 介绍的文章中,都可以找到一个术语:“保证 RVO 的复制省略”,这有点不言自明。但是搬家施工呢?

我们看下面的代码,很简单,有一个不可复制的类型,还有两个函数,一个是通过值取NonCopyable参数,第二个是通过右值引用来取。

#include <iostream>

struct NonCopyable
{
  NonCopyable() = default;
  NonCopyable(const NonCopyable&) = delete;

  NonCopyable(NonCopyable&& other) noexcept
  {
    std::cout << "Move ctor\n";
  }
};

void func_by_value(NonCopyable cp)
{
  auto x = std::move(cp);
}

void func_by_rvalue_ref(NonCopyable&& cp)
{
  auto x = std::move(cp);
}

int main() 
{
  std::cout << "Pass by value:\n";
  func_by_value(NonCopyable());

  std::cout << "\nPass by rvalue_ref\n";
  func_by_rvalue_ref(NonCopyable());
}

我使用 GCC(trunk) 编译了两次,使用以下标志,结果略有不同。

(1) -O0 -std=c++11 -fno-elide-constructors

程序输出: 按值传递: 移动 ctor 移动 ctor 通过 rvalue_ref 移动 ctor

(2) -O0 -std=c++17 -fno-elide-constructors

程序输出: 按值传递: 移动 ctor 通过 rvalue_ref 移动 ctor

所以我的问题是 - 在使用 C++17 时,移动限制被忽略有什么变化? Compiler explorer

【问题讨论】:

    标签: c++ c++17 copy-elision


    【解决方案1】:

    自从 C++17 mandatory elision of copy/move operations 被引入:

    在以下情况下,编译器必须省略类对象的复制和移动构造,即使复制/移动构造函数和析构函数具有可观察到的副作用。对象直接构建到存储中,否则它们将被复制/移动到。复制/移动构造函数不需要存在或可访问:

    • ...

    • 在一个对象的初始化中,当初始化表达式为 与 变量类型:

      T x = T(T(f())); // only one call to default constructor of T, to initialize x
      

    在prvalueNonCopyable()初始化参数cp时,需要省略move构造。请注意,强制复制省略适用于复制操作和移动操作。

    【讨论】:

      猜你喜欢
      • 2016-01-09
      • 2020-01-11
      • 1970-01-01
      • 2016-01-27
      • 1970-01-01
      • 2022-12-02
      • 2020-02-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多