我应该什么时候回来T const&
?如果我不打算修改对象,我看不出它与按值返回有何不同。通过 const 引用返回实际上只是意味着没有复制。所以什么时候返回T const&
有用。
6 回答
const&
您更愿意按价值而不是按价值返回的原因有两个。
首先是语义。返回某些内容的代码明确地const&
告诉调用者,“这是您所要求的只读版本。如果您想永久存储它或对其进行更改,您有责任制作它的副本。 " 这种返回类型的语义非常清晰,并且易于执行。
二是优化。通过按值返回某些内容,您从编译器中删除了一些优化机会。这并不是说按值返回比按返回效率低const&
(事实上,在相反的情况下可能是正确的——考虑一个char
在 64 位系统上返回 a 的函数)。它只是意味着您从编译器的优化工具箱中删除了其中一个工具。还有另一个工具可以替换它——即,将调用与复制省略一起内联——所以这可能是一种清洗。这一切都取决于上下文。
我提到“语义”作为第一个原因是因为我认为它是最重要的。优化的变量太多,移动的部分太多,通常很难知道编译器将能够使用哪些优化以及何时使用。然而,一件事始终是确定的——清晰的语义比混乱的语义更容易被人类理解。
您要返回的常见情况const T&
是const
getter 成员函数:
T& get() { return m_some_private_member; }
const T& get() const { return m_some_private_member; }
在这种情况下,您通常不想复制 - 您只想返回对某个对象的引用,并且为了 const 正确性,您可能还需要提供一个const
getter。
当你有一个足够稳定的物体时。
一个简单的案例是一个以这种方式返回内容的集合。有点像主要的职位描述。
对于非常量和另一种常见的情况是返回你在参数中得到的内容(包括隐藏的 this 指针)。这可能以类似的方式适用于 const& ,但要注意风险,当您的参数绑定到一个将在短时间内消失的临时变量时。如果你得到 & 并在更改内容后返回 const& 会更好。
您可以返回对数据成员的引用,但它符合“不要泄露您的胆量”准则。
在任何情况下,如果您返回 ref,您必须向客户提供有关有效性的文件。如果您开始制定该描述,您将首先发现它是否有意义。
另一个明显的例子是身份对象,可以(或假定)不被复制。拥有访问器是有意义的,一个返回 const& 供主流使用,另一个具有写访问权限。
不制作副本效率更高,尤其是对于复杂类型或在其复制构造函数中执行大量工作的类型。
由于您指定的原因:没有复制。
如果您要返回一个大对象,则返回一个 const 引用比返回该对象的副本更有效。
所以你可以避免你的功能像下面的那样被滥用?
class A
{
int x;
public:
int show()
{
return x;
}
A(int a)
{
x = a;
}
A const& operator+(A& inp)
{
inp.x = this->x + inp.x;
return inp;
}
};
int main()
{
A a(1),b(2),c(0),d(420);
a + b = d;
std::cout<<b.show();
}
这给出,420
作为输出。重载应该用作d = a + b
,但没有什么可以阻止返回的引用被分配另一个对象。
如果将函数的返回类型设置为A const&
返回的引用是常量,并且不能分配任何其他对象。因此,运算符只能用作d = a + b
而不是允许a + b = d
等。
g++ 给出错误error: passing ‘const A’ as ‘this’ argument of ‘A& A::operator=(const A&)’ discards qualifiers
并有效地防止这种滥用。