测试类:
#include <iostream>
#include <string>
struct inner
{
std::string value;
inner() : value("test") {
std::cerr << "inner default construct\n";
}
inner(inner &&mv) : value(std::move(mv.value)) {
std::cerr << "inner move construct\n";
}
inner(inner const ©) : value(copy.value) {
std::cerr << "inner copy construct\n";
}
};
struct outer
{
inner value;
outer() {}
outer(inner v)
: value(v)
{}
};
对移动语义的简单测试就是我所期望的:
inner mover(inner x)
{
return x;
}
int main()
{
inner i;
auto q = mover(std::move(i));
return 0;
}
......输出:
内部默认构造
内部移动构造
内部移动构造
但这个主要做了我没想到的事情:
int main()
{
inner i;
outer o(std::move(i));
return 0;
}
内部默认构造
内部移动构造
内部复制构造
我期待副本成为另一个举动,因为它是第一个主要的。为什么在第一种情况下使用移动优化而在第二种情况下不可用?
我意识到我可以在outer(inner v)
构造函数中显式调用std :: move ......但为什么需要这样做?为什么编译器不能进行隐式移动?
答案 0 :(得分:3)
您需要在初始化列表中说: value(std::move(v))
。
答案 1 :(得分:2)
我不是C ++ 11 rvalue sematics的专家,但outer
没有接受inner
rvalue引用的构造函数,因此编译器别无选择,只能生成{{1复制,因为inner
构造函数的输入参数是左值,因此在初始化outer
成员时必须调用inner
复制构造函数而不是移动构造函数。
您在outer::v
示例中未获得副本的原因可能是由Return Value Optimization引起的,如果输入mover()
实例可以直接移动,则无需任何副本目标inner
变量,从而调用q
移动构造函数而不是复制构造函数。