C++ 将局部变量声明为右值引用(例如T&&;r=移动(v)?
在某些情况下,你们能给我举个说明性的例子来证明下列陈述是有用和必要的吗C++ 将局部变量声明为右值引用(例如T&&;r=移动(v)?,c++,c++11,scope,move-semantics,rvalue-reference,C++,C++11,Scope,Move Semantics,Rvalue Reference,在某些情况下,你们能给我举个说明性的例子来证明下列陈述是有用和必要的吗 AnyTypeMovable v; AnyTypeMovable&& r = move(v); 否,AnyTypeMovable&&r=move(v)这里一点用处都没有 考虑以下代码: #include <iostream> #include <vector> class MyMovableType { int i; public: MyMova
AnyTypeMovable v;
AnyTypeMovable&& r = move(v);
否,
AnyTypeMovable&&r=move(v)代码>这里一点用处都没有
考虑以下代码:
#include <iostream>
#include <vector>
class MyMovableType
{
int i;
public:
MyMovableType(int val): i(val){}
MyMovableType(MyMovableType&& r) { this->i = r.i; r.i = -1; }
MyMovableType(const MyMovableType& r){ this->i = r.i; }
int getVal(){ return i; }
};
int main()
{
std::vector<MyMovableType> vec;
MyMovableType a(10);
MyMovableType&& aa = std::move(a);
vec.push_back(aa);
std::cout << a.getVal() << std::endl;
return 0;
}
将执行移动,因此打印输出将为-1
。因此,尽管您正在将aa
传递给push_back
,但仍然需要通过std::move
传递它。请注意,命名的rvalue是左值。所以您应该使用std::forward
#include <iostream>
#include <vector>
class MyMovableType
{
int i;
public:
MyMovableType(int val) noexcept : i(val){}
MyMovableType(MyMovableType&& r) noexcept { this->i = r.i; r.i = -1; }
MyMovableType(const MyMovableType& r) noexcept{ this->i = r.i; }
int getVal()const noexcept{ return i; }
};
int main()
{
std::vector<MyMovableType> vec;
MyMovableType a(10);
MyMovableType&& aa = std::move(a);
vec.push_back( std::forward<decltype(a)>(aa) );
std::cout << a.getVal() << std::endl; // -1 printed.
return 0;
}
#包括
#包括
类MyMovableType
{
int i;
公众:
MyMovableType(int-val)无例外:i(val){}
MyMovableType(MyMovableType&&r)不例外{this->i=r.i;r.i=-1;}
MyMovableType(constMyMovableType&r)不例外{this->i=r.i;}
int getVal()常量noexcept{return i;}
};
int main()
{
std::vec;
MyMovableType a(10);
MyMovableType&&aa=std::move(a);
向量向后推(标准:向前推(aa));
std::cout我可以说它相当无用,因为r
现在是一个左值(它有一个名称!),并且您需要std::move(r)
无论如何都要使其成为右值。有趣的事实:v
不需要移动。有趣的事实:这段代码中没有移动。我不会说这是100%无用的,你可以用它来告诉阅读下一段代码的人,这个变量是临时的,它将被移动,尽管我认为通常在std::move时很容易发现代码>被调用anyway@DavidRodríguez dribeas Devils AdvocateSo在此上下文中std::string&&
与std::string&
完全相同?这就是标准定义它的方式吗?@Haatschii:是的,命名的右值引用是左值。顺便说一句,第一个测试是不确定的。移动std::string
不需要原始的tring在任何特定状态下都被保留。它只需要是有效的,并且它具有相同的原始值就可以了。@R.MartinhoFernandes您是对的,我将编写一个简单的类。如果我理解正确,这里的std::forward调用将执行与std::move相同的操作(也就是说,它将最终移动前面调用std::move尚未移动的aa)--但是std::forward不应该在这里使用,因为它的目的是“转发”std::forward调用范围内未知的类型信息,并且所述信息在这里并不未知(即,我们知道aa的所有类型)。(注意-我刚刚了解了这方面的知识,我主要是在鹦鹉学舌地模仿斯科特·迈尔斯:)是的,保持std::forward以便正确地转发参数,而不是移动语义
#include <iostream>
#include <vector>
class MyMovableType
{
int i;
public:
MyMovableType(int val) noexcept : i(val){}
MyMovableType(MyMovableType&& r) noexcept { this->i = r.i; r.i = -1; }
MyMovableType(const MyMovableType& r) noexcept{ this->i = r.i; }
int getVal()const noexcept{ return i; }
};
int main()
{
std::vector<MyMovableType> vec;
MyMovableType a(10);
MyMovableType&& aa = std::move(a);
vec.push_back( std::forward<decltype(a)>(aa) );
std::cout << a.getVal() << std::endl; // -1 printed.
return 0;
}