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;

}