MyType
同时定义了副本和移动ctor。执行以下代码段时(使用VS2015编译后):
template<typename T>
void f(T&& o) {
// do something with o
}
int main() {
MyType o{ 1, 2, 3 };
f(o); // call of copy-constructor expected
f(std::move(o)); // call of move-constructor expected
}
我希望在第一次调用f
之后调用复制构造函数,并在第二次调用f
之后调用移动构造函数。但是在任何情况下都没有构造函数被调用。我怀疑这种行为是编译器优化,但我不确定可移植性或符合标准。
答案 0 :(得分:6)
两个调用都是引用 - 第一个是左值引用,第二个是 rvalue 引用。 T&&
适用于两者,称为forward reference(N4164)。 Scott Meyers称他们为universal references,作为模板参数和auto&&
特别有用。
std::move
用于表示所有权转移,但实际上并未采取任何行动。它的效果是一个static_cast到rvalue引用。
所以你有:
void f(MyType& ) {}
void f(MyType&& ) {}
...
f(o); // calls void f(MyType& )
f(static_cast<MyType&&>(o)); // calls void f(MyType&& )
通常在初始化对象时调用移动构造函数。
Move constructors cppreference.com
只要重载选择,就会调用移动构造函数 分辨率,通常在对象初始化时发生(通过 rvalue(xvalue或。)的直接初始化或复制初始化 prvalue)(直到C ++ 17)相同类型的xvalue(自C ++ 17开始),包括
初始化:
T a = std::move(b);
或T a(std::move(b));
,其中b的类型为T;函数参数传递:
f(std::move(a));
,其中a为T类型,f为void f(T t);
函数返回:
return a;
在T f()
之类的函数中,其中a是T类型,它有一个移动构造函数。
如果将f
更改为void f(T o)
,将为第一次调用调用复制构造函数,为第二次调用调用移动构造函数。