为什么const引用会延长右值的生命周期?

Why do const references extend the lifetime of rvalues?

本文关键字:生命 周期 const 引用 为什么      更新时间:2023-10-16

为什么c++委员会决定const引用应该延长临时对象的生命周期?

这个事实已经在网上进行了广泛的讨论,包括这里的stackoverflow。解释这种情况的权威资源可能是这个GoTW:

gotw# 88: " Most Important const "的候选对象

这个语言特性的基本原理是什么?大家知道吗?

(另一种选择是临时对象的生命周期不被任何引用延长。)


我自己最喜欢的理论是,这种行为允许对象隐藏实现细节。使用此规则,成员函数可以在返回值或对内部已经存在的值的const引用之间切换,而无需更改客户端代码。例如,一个矩阵类可能能够返回行向量和列向量。为了最小化副本,根据实现(主要是行还是主要是列),可以将其中一个或另一个作为引用返回。如果不能通过引用返回,则必须通过复制并返回该值来返回(如果返回的向量是连续的)。库编写者可能希望留有余地在将来更改实现(行主要还是列主要),并防止客户端编写强烈依赖于实现是行主要还是列主要的代码。通过要求客户端接受作为const ref的返回值,矩阵类可以返回const ref或值,而无需对客户端代码进行任何更改。无论如何,如果知道最初的原理,我想知道它。

于1993年提出。它的目的是消除绑定到引用时对临时的不一致处理。

那时候,还没有RVO(返回值优化)这样的东西,所以简单地禁止将临时对象绑定到引用会对性能造成影响。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0345.pdf

你不是在问为什么const引用被允许绑定到临时对象,而只是在问为什么它们延长了这些临时对象的生命周期。

考虑以下代码:

struct A
{
    void foo() const;
};
A bar();
const A& a = bar();
a.foo();               // (1)

如果bar()返回的临时对象的生命周期没有被延长,那么任何使用a(如(1)行)都会导致未定义的行为。这将使得将非形参const引用绑定到临时变量完全无用。


编辑(寻址OP的评论):

因此,真正的问题应该是为什么允许const引用变量(不是函数形参)绑定到临时变量。我不知道它最初的理由(理查德·霍奇斯的答案可能是唯一正确的),但它为我们提供了一个有用的功能。考虑下面的例子:
struct B
{
    virtual void foo() const;
};
B bar();
const B& b = bar();
b.foo();               // (1)

这个例子与上一个例子的唯一区别是B::foo()是虚拟的。现在,如果我们决定引入一个新的类D作为B的子类,并将bar()的返回类型从B更改为D呢?

struct B
{
    virtual void foo() const;
};
struct D : B
{
    virtual void foo() const;
};
//B bar();
D bar();
const B& b = bar();
b.foo(); // This will call D::foo()
// In the end the temporary bound by b will be correctly destroyed
// using the destructor of D.

因此,将const引用绑定到临时对象简化了对按值返回的对象的动态多态性的利用。