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

问题描述 投票:1回答:1

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

c++ c++11 c++14 move-semantics perfect-forwarding
1个回答
6
投票

两个调用都是引用 - 第一个是左值引用,第二个是和右值引用。 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开始)初始化对象(通过直接初始化或复制初始化)时(从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:return a;T f()之类的函数中,其中a是T类型,它有一个移动构造函数。

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


Universal vs Forwarding References in C++

© www.soinside.com 2019 - 2024. All rights reserved.