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

Why do const references extend the lifetime of rvalues?

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

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

GotW #88: A Candidate For the “Most Important const”

此语言功能的基本原理是什么?知道吗?

(替代方案是临时对象的生命周期不被任何引用延长。)


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

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

考虑这段代码:

struct A
{
    void foo() const;
};

A bar();

const A& a = bar();

a.foo();               // (1)

如果 bar() 编辑的临时 return 的生命周期没有延长,那么 a 的任何用法(以行 (1) 为例)都会导致未定义的行为.这将使对临时对象的绑定非参数 const 引用完全无用。


编辑(寻址):

因此,真正的问题应该是为什么允许将 const 引用变量(不是函数参数)绑定到临时变量。我不知道它最初的理由( 可能是唯一正确的理由),但它为我们提供了一个有用的功能。考虑以下示例:

struct B
{
    virtual void foo() const;
};

B bar();

const B& b = bar();

b.foo();               // (1)

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

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 引用绑定到临时变量简化了对 return 按值编辑的对象的动态多态性的利用。

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

那时候,还没有 RVO 这样的东西,所以简单地禁止将临时对象绑定到引用会影响性能。

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