Consider
class X
{
public:
std::unique_ptr<int> m_sp;
A m_a;
A test1()
{
return std::move(m_a);
}
A&& test2()
{
return std::move(m_a);
}
std::unique_ptr<int> test3()
{
return std::move(m_sp);
}
std::unique_ptr<int>&& test4()
{
return std::move(m_sp);
}
std::unique_ptr<int> test5()
{
return std::make_unique<int>(50);
}
};
class A
{
public:
A()
{
m_i = 1;
}
A(A&& other)
{
this->m_i = other.m_i;
other.m_i = -1;
}
A& operator=(A&& other)
{
this->m_i = other.m_i;
other.m_i = -1;
return *this;
}
int m_i;
};
To exercise these classes
X x;
A y;
y.m_i = 10;
y = x.test1();
X x2;
A y2;
y2.m_i = 10;
y2 = x2.test2();
both call A's move assignment but only in the test1 case do we call A's move constructor. Why is that? Is it because as we cannot return a A&& (std::move will cast A to A&&, but test1 says it must return an A).
In general, when one wants to move/transfer ownership of expensive member variables, do you want to specify the return to be an rvalue-reference (A&&) or an lvalue (A) type?
It feels a little unnatural as if you aren't using member variables, you let RVO/NRVO do it's thing and just return an lvalue. Take in the case of unique_ptr, when you've got an automatic variable you have a signature like test5(), but if you have a variable, not suitable for RVO/NRVO, like a member varaible should test3 or test4's signature be preferred.
Interested to know.
Thanks
Aucun commentaire:
Enregistrer un commentaire