![](/img/trans.png)
[英]C++ template member initialization: move-construction with rvalue but reference with lvalue
[英]Hidden move-construction
为什么有时候不会移动构造函数调用? 测试move-semantics (实时代码) :
struct Test {
int id;
Test(int id) : id(id) {
cout << id << " Test() " << endl;
}
~Test() {
cout << id << " ~Test() " << endl;
}
Test(const Test &t) : id(t.id) {
cout << id << " Test(const Test &t) " << endl;
}
Test(Test &&t) : id(t.id) {
cout << id << " Test(Test &&t) " << endl;
}
Test &operator=(const Test &t) {
cout << id << " operator=(const Test &t) " << endl;
return *this;
}
Test &operator=(Test &&t) {
cout << id << " operator=(Test &&t) " << endl;
return *this;
}
};
void f(Test z) {
cout << z.id << " f(Test z) " << endl;
}
int main() {
f(Test(1));
Test t(2); f(t);
}
输出:
1 Test()
1 f(Test t) <---// where is move constructor ?!
1 ~Test()
2 Test()
2 Test(const Test &t) <---// copy constructor of t(2)
2 f(Test t)
2 ~Test()
2 ~Test()
测试显示复制构造函数被调用。
但是,在f(Test(1));
之后f(Test(1));
调用函数f
而不为Test(1)
rvalue对象调用move-constructor。
它是隐式编译器优化吗? 或者我错过了重要的一点?
明确允许编译器忽略临时对象的复制(或移动)。 基本上,对象是在预期有效结果的地方构建的。 如果构造函数或析构函数具有副作用,则甚至允许使用此省略。
相关条款是12.8 [class.copy]第31段:
当满足某些条件时,允许实现省略类对象的复制/移动构造,即使为复制/移动操作选择的构造函数和/或对象的析构函数具有副作用。 在这种情况下,实现将省略的复制/移动操作的源和目标视为仅仅两种不同的引用同一对象的方式,并且该对象的销毁发生在两个对象的后期时间。没有优化就被破坏了。 在下列情况下允许复制/移动操作(称为复制省略)的这种省略(可以组合以消除多个副本):...
基本上可以使用复制省略的情况
return
语句时返回临时变量或局部变量。 throw
表达式时抛出临时变量或局部变量。 可以省略副本的确切条件列于12.8 [class.copy]第31段。
防止复制/移动省略的最简单方法是将其传递给返回合适引用的函数,例如,使用
f(std::move(Test(1)));
应该防止移动省略。
完成此讨论。 我们可以通过此选项在gcc中禁用此优化(复制省略):
-fno-elide-constructors
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.