本书The C++ Programming Language有这个关于默认操作的例子。我的问题集中在默认移动操作上。
struct S {
std::string a;
int b;
};
S f(S arg) {
S s0{};
S s1(s0); //s1 {s0}; in the book
s1 = arg;
return s1;
}
之后它说:
The copy construction of s1 copies s0.a and s0.b. The return of s1 moves s1.a and s1.b, leaving s1.a as the empty string and s1.b unchanged. Note that the value of a moved-from object of a built-in type is unchanged. That’s the simplest and fastest thing for the compiler to do.
我认为这意味着如果我写:
S s3{"tool",42};
f(s3);
既然s1的值被移动了,s1.a会变回“”而s1.b不变?那么当f()执行完,s1会被销毁吗? 我试图找到一种方法来测试我的猜测,但我找不到在函数执行后知道 s1 值的方法,因为它当然是本地的。我写了一个析构函数只是为了在它们被销毁之前找到值。
~S() {
std::cout << a << " " << b << '\n';
}
输出是:
0 //values of s0?
tool 42
tool 42
tool 42
看来我的猜测是完全错误的,我完全看不懂课文。谁能更清楚地解释引文中的文字?
最佳答案
首先,通过定义析构函数,您禁用了隐式移动构造函数。您必须添加到您的代码中:
S(const S&) = default;
S(S&&) = default;
S& operator=(const S&) = default;
S& operator=(S&&) = default; // not required here but should be added for completeness
然后,无论如何 RVO 开始发挥作用。如其他答案所述,允许编译器省略对复制和移动构造函数的调用。在 GCC 和 clang 中,您可以通过添加 -fno-elide-constructors
编译器选项来禁用它。之后你会得到这个输出:
42 // moved s1 (this can theoretically be different, because the value of s1.a is unspecified)
0 // s0
tool 42 // arg
tool 42 // return value of f()
tool 42 // s3
关于c++ - 默认移动构造,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26732417/