使用std :: move()创建r值引用变量有什么用处。 [C ++]

时间:2016-05-24 08:53:09

标签: c++ c++11 move-semantics

有人可以帮助我理解std::move吗?

我认为如果r值引用超出范围,那么如果使用std::move运算符分配它也会引用它。为什么以下代码不是这种情况?

#include<iostream>
using namespace std;

int main()
{
    string one = "1 - one";
    string two = "2 - two";
    {
        //not as expected
        string & lValRef = one;
        string && rValRef = std::move(two);
        string newS(rValRef);
    }
    cout << "one : " << one << endl;
    cout << "two : " << two << endl;
    {
        //as expected
        string temp(std::move(one));
        string tempAssignment;
        tempAssignment = std::move(two);
    }
    cout << "one : " << one << endl;
    cout << "two : " << two << endl;
    return 0;
}

你可以摆弄它here

我一直认为使用std::move是一种将对象置于“可删除状态”的方法。所以我很惊讶“两个&#39;第一次打印出来的东西。是否有任何用于创建&amp;&amp ;;我做的r值参考(&#39; rValRef&#39;)? [我明白在我的'rValRef&#39;周围需要std::move()。让它按照需要工作]。

以下是我自己的代码,我曾经帮助我更好地理解这一点。如果你愿意的话,请玩它:)代码here

#include <iostream>
#include <vector>
using namespace std;

class SimpleClass {
    friend ostream& operator<<(ostream & s,const SimpleClass & rhs);
private:
    vector<char> data;
public:
    SimpleClass(initializer_list<char> lst):data(lst.size()) {
        copy(lst.begin(),lst.end(),data.begin());
    }
    SimpleClass(size_t dim = 0):data(dim){};
    virtual ~SimpleClass() = default;
    SimpleClass(const SimpleClass & rhs) = default;
    SimpleClass & operator=(const SimpleClass & rhs) = default;
    SimpleClass(SimpleClass && rhs):data(move(rhs.data)){};
    SimpleClass & operator=(SimpleClass && rhs){
        if (this != &rhs){
            this->data = move(rhs.data);
            return *this;
        }
    }
};
ostream& operator<<(ostream & s,const SimpleClass & rhs){
    for (size_t i = 0; i != rhs.data.size(); ++i)
        s << rhs.data[i];

    return s;
}
int main()
{
    SimpleClass one = {'o','n','e'};
    SimpleClass two = {'t','w','o'};
    {
        SimpleClass & lValRef = one;
        SimpleClass && rValRef = std::move(two);
    }
    cout << "one : " << one << endl;
    cout << "two : " << two << endl;
    {
        SimpleClass temp(std::move(one));
        SimpleClass tempAssignment;
        tempAssignment = std::move(two);
    }
    cout << "one : " << one << endl;
    cout << "two : " << two << endl;
    return 0;
}

1 个答案:

答案 0 :(得分:5)

这里要理解的是,引用类型是与值类别不同的​​概念。

string && rValRef = std::move(two);
string newS(rValRef);

在第二行,rValRef的类型是std::string的右值引用,但rValRef的值类别是左值。一个很好的经验法则是,如果你可以取一些东西的地址,它可能是一个左值。 rValRef是一个命名变量,你可以获取地址,左值也是。

如果您想要从引用者实际移动,则需要再次调用std::move以使表达式具有正确的值类别(具体而言,std::move返回xvalue,这是一种右值):

string newS(std::move(rValRef));