C++11移动构造函数优化
C++11 Move constructor optimization
我目前正在尝试挂起move构造函数。我发现了以下(使用g++ d.cpp --std=c++11 -O3
编译)
class A {
string _x;
public:
A(string x) { cout << "default contrsutctor: " << x << "n"; _x = x; }
A(const A& other) { cout << "copy contrsutctor: " << other._x << "n"; _x = other._x; }
A(A&& other) { cout << "move contrsutctor: " << other._x << "n"; _x = other._x; }
A foo() {
cout << "foo: " << _x << "n";
return A("foo");
}
};
int main()
{
A a;
A b = a;
b.foo();
}
我希望这个输出:
default contrsutctor: a
move contrsutctor: a
foo: a
default contrsutctor: foo
但是输出是:
default contrsutctor: a
copy contrsutctor: a
foo: a
default contrsutctor: foo
为什么A b = a
行没有优化为使用move构造函数?之后永远不会使用a对象,所以优化代码以使用它而不是复制构造函数是安全的。
我知道我可以强制使用std::move()
调用move构造函数,但我更希望在这种情况下自动调用。
为什么A b=A行没有优化为使用move构造函数?
您可以在复制构造函数和移动构造函数中执行的操作可能完全不同。编译器不能保证这两个构造函数的结果是相同的。实现这种优化有可能改变程序的行为,从而打破"好像"规则。
您需要使用std::move
将a
强制转换为A&&
:
#include <utility>
int main()
{
A a("a");
A b = std::move(a);
b.foo();
}
移动构造函数的正确实现应该是:
A(A&& other)
: _x(std::move(other._x))
{}
在A b = std::move(a);
行之后, 正如@TonyD在评论中指出的那样,a
应为"空"。在这种情况下,a._x
将为空a._str
可能处于未指定但有效的状态(移动std:string的构造函数)。在这一行之后,应谨慎使用a
。
A b = a;
总是调用复制构造函数,无论它是否可以调用移动构造函数。此外,对象a
的生存期在分配之后继续,即使它不再被使用。
如果你想使用move构造函数,你必须明确它:
A b = std::move(a);
请注意,这可能很危险,因为移动后a
仍然可以访问。如果您以后不小心使用了它,可能会出现未定义的行为。
想想为什么它会自动发生。在您给出的示例中,没有必要,因为您还可以使用a
而不是b
。在许多更有意义的情况下,移动构造函数/赋值将自动使用,例如A a; a = foo();
。
为什么A b=A行没有优化为使用move构造函数?
因为这将改变程序的可观察行为。编译器不允许自由更改程序的可观察行为(§1.9/1),除非在非常特殊的情况下(§12.8/31)。这不是这些情况之一。从构造函数中删除副作用,编译器可能会对其进行优化。当然,如果你去掉了副作用,那么你就不会注意到编译器是否优化了构造函数调用(除非你检查了程序集或二进制输出),但这就是重点。
- "error: no matching function for call to"构造函数错误
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 使用仅使用一次的变量调用的复制构造函数.这可能是通过调用move构造函数进行编译器优化的情况吗
- 这个C++编译器优化(在自身的实例上调用对象自己的构造函数)的名称是什么,它是如何工作的?
- 何时允许编译器优化复制构造函数
- 编译器是否优化了默认移动构造函数?
- C 构造函数成员分配优化
- 编译时,复制构造函数/复制分配和正常功能调用优化之间是否存在任何区别
- 实现move构造函数如何影响返回值优化
- -fno elide构造函数是否包含在-O0或任何其他优化级别中
- 针对构造函数的编译器优化
- 返回值优化是否需要声明一个复制构造函数
- 从具有移动语义或返回值优化的函数返回值,但不返回复制构造函数
- 使c++编译器优化到在map初始化时只调用构造函数一次
- 由于构造函数初始值设定项列表而优化
- 如果没有定义Move语义(Move构造函数和Move赋值操作符),编译器是否默认优化
- 构造函数中的通用引用和返回值优化(rvo)
- 隐式构造函数转换的编译器优化
- C++11移动构造函数优化
- 复制省略和返回值优化相对于复制构造函数