我正在尝试很好地学习 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;
}
}
我非常怀疑编译器是否真的会这样做。请注意,在创建 v1
和 v2
之前,在每个代码路径中返回的对象都是已知的,因此优化器可以在重写后在返回位置找到正确的对象。
12.8/31 中描述了可以省略复制/move 的情况。如果您设法编写不属于这些类别的代码并且该类型具有 move 构造函数,则将调用 move 构造函数。
关于c++ - 是否有一个不会被省略的 move 构造的简单示例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12285811/