提问者:小点点

C 17在移动省略方面发生了什么变化


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

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

#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(主干)编译了两次,结果略有不同。

(1)-O0-std=c 11-fno-elide构造函数

Program output: 

Pass by value:
Move ctor
Move ctor

Pass by rvalue_ref
Move ctor

(2)-O0-std=c 17-fno-elide构造函数

Program output:

Pass by value:
Move ctor

Pass by rvalue_ref
Move ctor

所以我的问题是-使用C 17时省略了移动收缩有什么变化?编译器资源管理器


共1个答案

匿名用户

由于引入了C 17强制省略复制/移动操作:

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

>

  • ...

    在对象的初始化中,当初始化表达式是与变量类型相同的类类型(忽略cv限定)的正则表达式时:

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

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

  • 相关问题