使用 std::move() 创建右值引用变量有什么用吗? [C++]
Is there any use in creating a r-value reference variable using std::move(). [C++]
谁能帮我修正一下对 std::move
的理解?
我认为如果右值引用超出范围,如果它是使用 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;
}
您可以 fiddle 使用它 here。
我一直认为使用 std::move
是一种将对象留在 'deletable state' 中的方法。所以我很惊讶 'two' 第一次打印出任何东西。像我一样 ('rValRef') 创建一个 && r 值引用有什么用吗? [我知道我的 'rValRef' 周围需要一个 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;
}
这里要理解的是,引用类型是一个独立于值类别的概念。
string && rValRef = std::move(two);
string newS(rValRef);
在第二行,rValRef
的类型是对 std::string
的右值引用,但 rValRef
的值类别是左值。一个很好的经验法则是,如果你可以获取某物的地址,它可能是一个左值。 rValRef
是一个命名变量,您可以获取其地址,左值也是如此。
如果你想真正从referencee移动,你需要再次调用std::move
以便表达式有正确的值类别(具体来说,std::move
returns一个xvalue,这是一种右值):
string newS(std::move(rValRef));
谁能帮我修正一下对 std::move
的理解?
我认为如果右值引用超出范围,如果它是使用 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;
}
您可以 fiddle 使用它 here。
我一直认为使用 std::move
是一种将对象留在 'deletable state' 中的方法。所以我很惊讶 'two' 第一次打印出任何东西。像我一样 ('rValRef') 创建一个 && r 值引用有什么用吗? [我知道我的 'rValRef' 周围需要一个 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;
}
这里要理解的是,引用类型是一个独立于值类别的概念。
string && rValRef = std::move(two);
string newS(rValRef);
在第二行,rValRef
的类型是对 std::string
的右值引用,但 rValRef
的值类别是左值。一个很好的经验法则是,如果你可以获取某物的地址,它可能是一个左值。 rValRef
是一个命名变量,您可以获取其地址,左值也是如此。
如果你想真正从referencee移动,你需要再次调用std::move
以便表达式有正确的值类别(具体来说,std::move
returns一个xvalue,这是一种右值):
string newS(std::move(rValRef));