为什么临时的“测试”没有移动,而只是构造了?

时间:2019-07-28 18:15:40

标签: c++ class rvalue-reference

我正在阅读Scott Meyers的《 Effective Modern C ++》一书,其中作者提到了

  

for i in range(0,len(data.index)): ... ... if data.at[i,'BestP_A'] == 'Bra': polemin = [data.loc[i,'Bra'],data.loc[i,'Nah'],data.loc[i,'Tec'],data.loc[i,'Ryc'],data.loc[i,'Hla']] data.at[i,'BestP_Min'] = min(polemin) data.at[i,'BestP_Idx'] = polemin.index(min(polemin)) elif data.at[i,'BestP_A'] == 'Obr': polemin = [data.loc[i,'Obr'],data.loc[i,'Nah']... 的副本通常是移动构建的,而   rvalues通常是副本构建的。”

所以我想通过编写一个lvalues类来测试它,该类将临时构造到一个Test函数中,该函数将右值引用作为dummy类的参数。 / p>

我希望看到上述报价的输出,如:

Test

但是我只有:

Constructed...
Moving...
Hello world

为什么移动构造函数未调用?是否像Constructed... Hello world 一样将临时传递给dummy有任何未定义的行为?我正在使用C ++ 17。

代码如下:

dummy(Test{});

2 个答案:

答案 0 :(得分:1)

出于相同的原因,以下代码不会调用复制构造函数:

guard compareArray2.count == createDateArray.count else { return false}
for i in 0..<compareArray2.count {
    if df.string(from: compareArray2[i]) != df.string(from: createDateArray[i]) {
        return false
    }
}
return true

...因为该对象是通过引用传递的。在上面的代码中,它是一个左值引用,而在您给出的示例中是一个右值引用,但仍然是一个引用。

如果要按值传递它,则需要在函数参数类型中反映出来:

class Test {
   ...
};

void dummy(Test& t) { // passed as an lvalue reference
   test.print();
}

int main() {
   Test t;
   dummy(t);
   return 0;
}

然后需要调用构造函数以按值传递void dummy(Test t) { ... } ,除非发生复制省略,请参见下面的补充内容

请注意,t实际上不会移动任何东西。它将输入转换为右值引用并返回。


尽管有一些细微差别。 C ++ 17保证不会为prvalue分配创建临时目录,即std::move在这种情况下不会调用copy或move构造函数,因为省去了创建临时目录。尽管该语言没有要求,但在C ++ 17之前的版本中仍可能会发生复制省略。因此,如果您想观察通过将prvalue dummy(Test{})按值传递给-fno-elide-constructors函数(如上例所示)时调用move构造函数,请确保设置Test{}编译器标志。

答案 1 :(得分:-1)

基本上,仅构造一个Test实例:dummy(Test{}),但此举表示如果要从一个实例移到另一个实例,则至少存在两个实例。