std :: forward和copy构造函数

时间:2015-06-06 00:55:50

标签: c++ templates c++11 perfect-forwarding

我最近开始学习C ++。我在std :: forward上有一个关于左值引用和右值引用的问题。 根据我的理解,以下代码中的Func(mc)假设要调用 Func(T& t)因为模板参数扣除规则。并且应该在函数内部使用消息“复制构造函数”调用MyClass的复制构造函数。但是,当我运行程序时,我无法得到它。 我检查了带有右值引用的std :: forwad,并且复制构造函数在其他行中运行良好。  请帮我理解代码中发生的事情。如果我容易犯错误或误解,我很抱歉花时间。非常感谢你。

class MyClass {
public:
    MyClass() { printf("constructor.\n"); };
    MyClass(MyClass&) { printf("copy constructor.\n"); };
    MyClass(const MyClass&) { printf("const copy constructor.\n"); };
    MyClass(MyClass&&) { printf("move constructor.\n"); };
    int val = 3;
};

template <typename T>
void Func(T&& t) {
    T new_t_(std::forward<T>(t));
    new_t_.val *= 2;
};

main() {
    MyClass mc;
    Func(mc);  // lvalue <- Func(T&)
    Func(MyClass());  // rsvalue <- Func(T&&)
    printf("mc.val=%d\n", mc.val); // this is for check

    MyClass mc2(mc);  // this is for check of copy constructor
}

运行程序时的输出如下,

constructor.
constructor.
move constructor.
mc.val=6
copy constructor.

我认为它应该在第一个和第二个“构造函数”消息之间有“复制构造函数”。

再次感谢你。

1 个答案:

答案 0 :(得分:5)

Func(mc);

此调用会将T推断为MyClass&。请注意参考。这是由于在C ++中引入了完美转发的方式:如果T&& Func函数参数T的{​​{1}}函数参数将被推导为<左>参考。对应的函数参数是一个左值表达式;否则(对于xvalues和prvalues),它不会被推断为引用类型。

然后,&&推导出的类型将使用函数参数T&& t中的Func(mc)进行引用折叠,以形成最终的函数参数类型。在T == MyClass&MyClass& &&的情况下,函数参数变为MyClass&,折叠为T == MyClass&

new_t_开始,在这种情况下,局部变量template <> void Func<MyClass&>(MyClass& t) { MyClass& new_t_(std::forward<MyClass&>(t)); new_t_.val *= 2; } 的声明将声明引用。不会创建新对象:

Func(MyClass());
MyClass()

这里,函数参数是prvalue-expression TMyClass将被推断为template <> void Func<MyClass>(MyClass&& t) { MyClass new_t_(std::forward<MyClass>(t)); new_t_.val *= 2; } (未经参考)。生成的函数模板实例化如下所示:

std::decay

如果要将函数参数复制/移动到局部变量中,可以使用std::remove_reference元函数 - 或者更具体地针对OP的问题,template <typename T> void Func(T&& t) { using DT = typename std::decay<T>::type; DT new_t_(std::forward<T>(t)); new_t_.val *= 2; } 元函数。 E.g。

<TextBox Name="blah" KeyDown="TextboxKEYDOWN">