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

No constructor called when calling function

MyType 定义了复制和移动构造函数。执行以下代码片段时(使用 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 之后调用移动构造函数。但是在任何情况下实际上都没有调用构造函数。我怀疑此行为是编译器优化,但不确定可移植性或是否符合标准。

这两个调用都是通过引用 - 第一个是 lvalue 引用,第二个是 rvalue 引用。 T&& 与两者一起使用,称为 forward reference (N4164). Scott Meyers called them universal references 并且作为模板参数和 auto&&.

特别有用

std::move用于表示所有权转移但实际上不做任何动作。它的效果是 static_cast 到右值引用。

所以你有:

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

The move constructor is called whenever selected by overload resolution, which typically occurs when an object is initialized (by direct-initialization or copy-initialization) from rvalue (xvalue or prvalue) (until C++17)xvalue (since C++17) of the same type, including

  • initialization: T a = std::move(b); or T a(std::move(b));, where b is of type T;

  • function argument passing: f(std::move(a));, where a is of type T and f is void f(T t);

  • function return: return a; inside a function such as T f(), where a is of type T which has a move constructor.

如果将 f 更改为 void f(T o),将在第一次调用时调用复制构造函数,在第二次调用时调用移动构造函数。


Universal vs Forwarding References in C++