我应该什么时候通过 T const& 返回?

When should I return by T const&?

本文关键字:返回 const 什么时候 我应该      更新时间:2023-10-16

我应该什么时候返回T const&?如果我不打算修改对象,我看不出它与按值返回有什么不同。通过 const 引用返回实际上只是意味着不制作副本。所以什么时候返回T const&有用。

您更愿意按const&而不是按值返回有两个原因。

首先是语义。 通过const&返回某些内容的代码明确地告诉调用者,"这是您请求的内容的只读版本。 如果您想永久存储它或对其进行更改,您有责任制作它的副本。 此返回类型的语义非常清晰,并且易于执行。

二是优化。 通过按值返回某些内容,可以从编译器中删除一些优化机会。 这并不是说按值返回的效率低于按const&返回的效率(事实上,在相反的情况下可能是正确的 - 考虑一个在 64 位系统上返回char的函数(。 它只是意味着您从编译器的优化工具箱中删除其中一个工具。 还有另一个工具可以替换它 - 即内联调用和复制省略 - 所以这可能是一个洗涤。 这一切都取决于上下文。

我提到"语义"是第一个原因,因为我认为它是最重要的。 优化的变量如此之多,活动部件如此之多,以至于通常很难知道编译器将能够采用哪些优化以及何时使用。 然而,有一件事是肯定的——清晰的语义比混乱的语义更容易被人类理解。

返回 const T& 的常见情况是 const getter 成员函数:

T& get() { return m_some_private_member; }
const T& get() const { return m_some_private_member; }

在这种情况下,您通常不想制作副本 - 您只想返回对某个对象的引用,并且为了恒定正确性,您可能还需要提供一个const getter。

当你有一个足够稳定的对象时。

一个简单的例子是,对于以这种方式返回内容的集合。有点主要的职位描述。

对于 nonconst 和另一种常见情况是返回您在参数中得到的内容(包括隐藏的 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,并有效地防止了这种滥用。