为什么在这种情况下不调用move-ctor


#include <iostream>
using namespace std;
class Test {
public:

Test(string value){
cout<<"Ctor "<<value<<endl;
_val=value;
}
Test( Test&& mv): _val(mv._val)
{
mv._val=string();
cout<<"Mv constructor"<<endl;  
}

string& get()
{
return this->_val;
}
private:
string _val;
};
void print(Test&& t)
{
cout<<"Stampa val is "<<t.get()<<endl;
}
int main()
{
Test a{"ciao"};
print(move(a));
cout<<"Val of a is "<<a.get()<<endl;
print(Test("test"));

return 0;
}

其输出为(将行号添加到stdout(:

Ctor ciao
Stampa val is ciao
a的val is ciao
Ctor test
Stampa val is test

为什么在第2行主要没有调用mv语义?我可能理解第四行有一个优化,所以只调用构造函数,但我无法解释第一步。有什么想法吗?

std::move只是将参数转换为右值(稍后可以移动(,它本身不执行移动操作。转换后的右值绑定到引用参数t,因此在这种情况下不会调用move构造函数。

std::move用于指示对象t可能是";从";,即允许将资源从t有效地转移到另一个对象。

特别是,std::move生成一个标识其参数t的xvalue表达式。它完全等效于右值引用类型的static_cast。

Move构造函数通常被调用来初始化对象,它不会在引用绑定中被调用(对于左值引用也是如此(。如果您将参数更改为按值传递,则将使用move构造函数(初始化参数(。例如

void print(Test t)
{
cout<<"Stampa val is "<<t.get()<<endl;
}

实时


BTW:即使在更改为传递值print(Test("test"));之后,由于复制省略,也不会调用移动构造函数。

BTW2:在move构造函数中,最好基于std::string提供的move操作来移动初始化数据成员val。例如

Test( Test&& mv): _val(std::move(mv._val))
{
cout<<"Mv constructor"<<endl;  
}

您的代码中只构造了两个Test对象,而不是更多。

int main()
{
Test a{"ciao"};                          // here 
print(move(a));
cout<<"Val of a is "<<a.get()<<endl;
print(Test("test"));                     // and here
}

第二个也通过Test(string)构造函数构造对象。std::move不构造对象,它只是对右值引用的强制转换。将该右值引用传递给print也不需要构造另一个Test。如果你想调用构造函数,你必须实际构造一个实例,例如:

auto t  = Test( std::move(a) );     // calls Test(Test&&)
auto t2 = Test( Test("move me") );  // calls Test(string) then Test(Test&&)

最新更新