调用std::move返回值-签名应该是什么



考虑

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;
};

练习这些课程

X x;
A y;
y.m_i = 10;
y = x.test1();
X x2;
A y2;
y2.m_i = 10;
y2 = x2.test2();

两者都调用A的move赋值,但只有在test1的情况下,我们才会调用A的移动构造函数。为什么?是因为我们不能退回a&amp;(std::move会将A强制转换为A&&,但test1表示必须返回A(。

通常,当想要移动/转移昂贵成员变量的所有权时,您想将返回指定为右值引用(A&&(还是左值(A(类型?

这感觉有点不自然,好像你没有使用成员变量,你让RVO/NRVO做它的事情,只返回一个左值。以unique_ptr为例,当你有一个自动变量时,你会有一个像test5((这样的签名,但如果你有一种不适合RVO/NRVO的变量,比如一个成员可变,应该首选test3或test4的签名。

有兴趣了解。

感谢

这里存在语义差异。当您返回像中那样的对象时

A test1()
{
return std::move(m_a);
}
std::unique_ptr<int> test3()
{
return std::move(m_sp);
}

然后你总是离开你的会员。无论调用者是否使用返回值执行某些操作,您都将从X移到临时的。所有权不再属于你。调用者可以接管返回值。如果调用方忽略返回值,那么临时文件无论如何都会被销毁。另一方面,如果你返回一个右值引用,就像在中一样

A&& test2()
{
return std::move(m_a);
}
std::unique_ptr<int>&& test4()
{
return std::move(m_sp);
}

您只是向调用者提供了从/接管对象所有权的机会。如果调用方不执行移动,则X将保留所有权,对象将不会移动。

需要理解的关键是,与名称所暗示的相反,std::move()实际上并没有执行移动。它只允许从中移动给定的对象。实际移动由相应类型的移动构造函数或移动赋值运算符执行。

所以你的答案是:这取决于你想表达什么。如果你归还了一个物体,你会说"如果你想要的话,我会把它扔掉:它就在那里"。如果你返回一个右值引用,你会说"这就是问题所在,现在是你接受它的机会,否则我会保留它"…

相关内容

  • 没有找到相关文章

最新更新