c++ - 是否有一个不会被省略的 move 构造的简单示例?

标签 c++ c++11 move-semantics

我正在尝试很好地学习 move 语义,以便将它介绍给我的学生。我一直在使用高度简化的类似 vector 或类似字符串的类来管理内存,并且其成员输出消息以演示它们的事件。我正在尝试开发一组简单的示例来向学生展示。

在 gcc 4.7 和 clang 中,RVO 和其他地方的构造省略积极地消除了复制和 move 构造,所以虽然我可以很容易地看到 move 分配在工作,但我唯一一次看到 move 构造在工作是如果我关闭构造省略在带有 -fno-elide-constructors 的 gcc 4.7 中。

显式复制构造语句

MyString newString(oldString);

即使启用了省略,也会调用复制构造函数。但是像

MyString newString(oldString1 + oldString2); 

因为省略而没有调用 move 构造函数。

任何明确使用 std::move 的东西都不会成为一个简单的例子,因为解释 std::move 必须稍后再做。

所以我的问题是:是否有一个简单的代码示例可以调用 move 构造,即使复制/move 构造函数被省略?

最佳答案

这个简单的例子是返回函数的参数。该标准明确禁止在这种情况下省略 move (并不是说他们可以...):

std::vector<int> multiply( std::vector<int> input, int value ) {
   for (auto& i : input )
      i *= value;
   return input;
}

此外,您可以明确请求 move 构造以获得更简单但更人工的示例:

T a;
T b( std::move(a) );

嗯...还有一个不涉及std::move(技术上可以省略,但大多数编译器可能不会):

std::vector<int> create( bool large ) {
   std::vector<int> v1 = f();
   std::vector<int> v2 = v1;       // modify both v1 and v2 somehow
   v2.resize( v2.size()/2 );
   if ( large ) {
      return v1;
   } else {
      return v2;
   }
}

虽然优化器可以通过重写代码来忽略它:

std::vector<int> create( bool large ) {
   if ( large ) {
      std::vector<int> v1 = f();
      std::vector<int> v2 = v1;       // modify both v1 and v2 somehow
      v2.resize( v2.size()/2 );
      return v1;
   } else {
      std::vector<int> v1 = f();
      std::vector<int> v2 = v1;       // modify both v1 and v2 somehow
      v2.resize( v2.size()/2 );
      return v2;
   }
}

我非常怀疑编译器是否真的会这样做。请注意,在创建 v1v2 之前,在每个代码路径中返回的对象都是已知的,因此优化器可以在重写后在返回位置找到正确的对象。

12.8/31 中描述了可以省略复制/move 的情况。如果您设法编写不属于这些类别的代码并且该类型具有 move 构造函数,则将调用 move 构造函数。

关于c++ - 是否有一个不会被省略的 move 构造的简单示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12285811/

相关文章:

c++ - 如何在 C++ 中访问 map 中的 map ..?性能问题?

c++ - 通过引用传递数组到线程

c++ - 为什么在 lambda 中 move 时不调用 move 构造函数?

c++ - 传递右值与左值 vector

c++ - 在 std::move 之后重用 std 容器是否安全?

c++ - 类属性包括模板类的实例(错误 C3857)

c++ - 一个 "source-less"C++ 习语

c++ - 如何避免前向声明?

c++ - 如何使 std::sort 在 std::swap 和我的 namespace 的模板化交换之间没有名称冲突?

c++ - 如何找出 C++ 警告的编号