在阅读了一些有关右值参考的材料后,我有更多问题然后答案。从这里我读到了rvalue ref:
这里我举了一个简单的例子来帮助我理解:
#include <iostream>
using namespace std;
class A
{
public:
A() :m_a(0), m_pa(nullptr) { cout << "constructor call" << endl; };
~A() { cout << "destructor call" << endl; };
A(A& other) :m_a(0), m_pa(nullptr)
{
cout << "copy constructor" << endl;
}
A(A&& other) :m_a(0), m_pa(nullptr)
{
cout << "move constructor" << endl;
}
A& operator=(A&& other)
{
this->m_a = other.m_a;
this->m_pa = other.m_pa;
other.m_a = 0;
other.m_pa = nullptr;
return *this;
}
A& operator=(A& other)
{
this->m_a = other.m_a;
this->m_pa = other.m_pa;
other.m_a = 0;
other.m_pa = nullptr;
return *this;
}
private:
int m_a;
int* m_pa;
};
int main()
{
A(test2);//constructor
A test4(test2);//copy constructor
//? - move constructor
return 0;
}
我不明白&amp;&amp;的特别之处。在上面的例子中,我可以用&amp;。
做这样的事情A& operator=(A& other)
{
this->m_a = other.m_a; //copy value
this->m_pa = other.m_pa;//copy pointer address
other.m_a = 0;
other.m_pa = nullptr;//clean "other" object properties from preventing destructor to delete them and lose pointer address
return *this;
}
问题:
示例2:
#include <iostream>
using namespace std;
void printReference (int& value)
{
cout << "lvalue: value = " << value << endl;
}
void printReference (int&& value)
{
cout << "rvalue: value = " << value << endl;
}
int getValue ()
{
int temp_ii = 99;
return temp_ii;
}
int main()
{
int ii = 11;
printReference(ii);
printReference(getValue()); // printReference(99);
return 0;
}
问题:
答案 0 :(得分:1)
在您阅读了一些关于右值的内容之后,这里有一些关于右值的more材料 我认为你可能缺少的一点,不是(仅)你可以做什么,而是应该做什么。
您的第一个示例有几个问题:
您无法将const值复制到A
的实例。
const A a1;
A a2(a1); // won't compile
A a3;
a3 = a1; // won't compile
我不明白&amp;&amp;的特别之处。在上面的例子中,我可以用&amp;。
做这样的事情
是的,你可以做你的建议。但它是纯粹设计的副本分配。考虑一下:
我写了一个共享库,我的副本ctor就像你在你的建议中所做的那样。您无权访问我的代码,只能访问标题。在我的副本ctor和assigment运算符中,我获取了传递给我的库的你实例的所有权。没有描述作业正在做什么......你是否明白了这一点,我不能取得你的实例的所有权!例如:
// my header:
// copy ctor
A& operator=(A& other);
// your code:
A a1;
A a2(a1); // from now on, a1 is broken and you don't know it!!!
cout << a1; // pseudo code: prints garbage, UD, crash!!!
您始终应该定义copy-ctors / assignments参数 const :
A(A const& other);
A& operator=(A const& other);
// ...
const A a1;
A a2(a1); // will compile
A a3;
a3 = a1; // will compile + due to the fact a1 is passed const a3 cannot mutate a1 (does not take ownership)
cout << a1; // pseudo code: everything is fine
a3 = std::move(a1); // a3 takes ownership from a1 but you stated this explicitly as you want it
Here是一个可以玩的小例子。请注意,复制构造函数是const,但复制赋值不是。然后你可以看到他们的不同之处。
答案 1 :(得分:0)
如果我可以用&amp;不使用额外的内存分配和复制操作我为什么要使用&amp;&amp;?
你写的&
左值引用的赋值运算符非常非常糟糕。你不希望发表像
a = b;
损坏 b
,但那是你的建议。通常的赋值运算符精确地使用const&
,因为它不应该改变表达式的右侧。
因此,当你做想要窃取右手边的状态时,你应该使用rvalue-reference赋值运算符(移动赋值),例如当它出现时。是一个匿名的临时或你明确move
它:
a = return_anonymous_temporary(); // ok: the rhs value would expire anyway
a = std::move(b); // ok: the damage to b is explicit now
但这种行为不应该是默认行为。
答案 2 :(得分:0)
如果我可以用&amp;不使用额外的内存分配和复制操作我为什么要使用&amp;&amp;?
因为它允许你为rvalues和lvalues重载一个函数,并且每个函数都有不同的行为。您在两个重载中都有相同的行为,因此在这种情况下您不需要右值引用。
更一般地说,rvalue引用参数允许您传递临时值,同时允许从该参数移动。
为什么要使用&amp;&amp;在这种情况下,这对我有什么帮助?
当参数为右值时,它允许您打印"rvalue"
。
为什么不直接存储getValue的返回值并将其打印出来?
然后,您无法为左值打印"rvalue"
,为左值打印"lvalue"
。
除了移动构造函数/赋值运算符之外,r值非常有用的情况并不多。