是否有一个简单的移动构造示例,不会被忽略?

use*_*444 7 c++ move-semantics c++11

我正在努力学习移动语义,以便将它介绍给我的学生.我一直在使用高度简化的矢量或类似字符串的类来管理内存,其成员输出消息来演示它们的活动.我正在尝试开发一组简单的例子来向学生展示.

RVO和其他地方的gcc 4.7和clang的施工设备积极地消除了复制和移动施工,所以虽然我可以很容易地看到工作中的移动分配,但我唯一一次看到移动施工在工作中是因为我关闭了gcc 4.7中的建筑省略与-fno-elide-constructors.

显式复制构造语句

MyString newString(oldString);
Run Code Online (Sandbox Code Playgroud)

即使启用了elision,也会调用复制构造函数.但有点像

MyString newString(oldString1 + oldString2); 
Run Code Online (Sandbox Code Playgroud)

由于省略,因此不会调用移动构造函数.

任何明确使用std :: move的东西都不会成为一个简单的例子,因为解释std :: move必须在以后出现.

所以我的问题是:是否有一个简单的代码示例,即使复制/移动构造函数被删除,也会调用移动构造?

Dav*_*eas 7

这个简单的例子是返回函数的参数.标准明确禁止在这种情况下忽略移动(不是他们可以......):

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

此外,您可以明确地请求移动构造以获得更简单的结构,尽管这是一个更人为的例子:

T a;
T b( std::move(a) );
Run Code Online (Sandbox Code Playgroud)

嗯...还有一个不涉及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;
   }
}
Run Code Online (Sandbox Code Playgroud)

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

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;
   }
}
Run Code Online (Sandbox Code Playgroud)

我非常怀疑编译器实际上会这样做.请注意,在每个代码路径中,之前已知的对象都是已知的v1并且v2已创建,因此优化程序可以在重写后在返回位置中找到正确的对象.

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