调用函数时没有调用构造函数

时间:2017-12-15 19:30:41

标签: c++ c++11 c++14 move-semantics perfect-forwarding

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之后调用移动构造函数。但是在任何情况下都没有构造函数被调用。我怀疑这种行为是编译器优化,但我不确定可移植性或符合标准。

1 个答案:

答案 0 :(得分:6)

两个调用都是引用 - 第一个是左值引用,第二个是 rvalue 引用。 T&&适用于两者,称为forward referenceN4164)。 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),将为第一次调用调用复制构造函数,为第二次调用调用移动构造函数。

Universal vs Forwarding References in C++