我试图理解rvalue引用并移动语义。在下面的代码中,当我将10传递给Print函数时,它会调用rvalue reference overload,这是预期的。但究竟发生了什么,10将被复制(或从它引用的地方)。其次std::move
实际上做了什么?它是从i
中提取值10然后通过吗?或者是编译器使用右值参考的指令?
void Print(int& i)
{
cout<<"L Value reference "<<endl;
}
void Print(int&& i)
{
cout<<"R Value reference "<< endl;
}
int main()
{
int i = 10;
Print(i); //OK, understandable
Print(10); //will 10 is not getting copied? So where it will stored
Print(std::move(i)); //what does move exactly do
return 0;
}
感谢。
答案 0 :(得分:9)
在10
的情况下,可能会涉及优化,这将改变实际的实现,但从概念上讲,会发生以下情况:
创建临时int
并使用值10
进行初始化。
临时int
绑定到r值引用函数参数。
从概念上讲,没有复制 - 引用将引用临时。
对于std::move()
:可能存在一些与引用等相关的棘手位,但主要是,它只是一个转换为r值引用。 std::move()
实际上移动任何内容。它只是将其参数转换为r值,以便可以从中移动。
无论如何,“移动”实际上并不是一个定义的操作。虽然考虑移动很方便,但重要的是l值与r值的区别。
“移动”通常由移动构造函数,移动赋值运算符和带有r值引用的函数(例如push_back()
)实现。正是他们的实现使得移动成为实际的移动 - 也就是说,它们被实现以便他们可以“窃取”r值的资源而不是复制它们。那是因为,作为一个r值,它将不再可访问(或者你承诺编译器)。
这就是std::move()
启用“移动”的原因 - 它将其参数转换为r值,信号,“嘿,编译器,我不再使用这个l值,你可以让函数(如作为移动ctors)将其视为r值并从中窃取。“
答案 1 :(得分:8)
但究竟会发生什么,10将被复制(或从其引用的地方)
创建临时值,并将引用传递给函数。 Temporaries是 rvalues ,因此可以绑定到 rvalue 引用;所以选择了第二次过载。
其次
std::move
实际上做了什么?
它为您的参数提供 rvalue 引用。它等同于(根据定义)static_cast<T&&>
。
尽管有这个名字,它本身并没有任何动作;它只是为您提供了一个可用于移动值的引用。
答案 2 :(得分:-1)
std::move
int
通过int&&
投放static_cast<int&&>
。
最终,如果类型是class
或struct
,则调用(隐式或显式)移动构造函数将被调用,而不是copy constructor
/ classical constructor
。< / p>