为什么 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 类型从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 引用绑定到临时变量简化了对 return 按值编辑的对象的动态多态性的利用。
它于 1993 年提出。其目的是消除绑定到引用时对临时对象的不一致处理。
那时候,还没有 RVO 这样的东西,所以简单地禁止将临时对象绑定到引用会影响性能。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0345.pdf
为什么 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 类型从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 引用绑定到临时变量简化了对 return 按值编辑的对象的动态多态性的利用。
它于 1993 年提出。其目的是消除绑定到引用时对临时对象的不一致处理。
那时候,还没有 RVO 这样的东西,所以简单地禁止将临时对象绑定到引用会影响性能。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/1993/N0345.pdf