为什么const引用会延长右值的生命周期?
Why do const references extend the lifetime of rvalues?
为什么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引用绑定到临时对象简化了对按值返回的对象的动态多态性的利用。
- 如何在共享库的整个生命周期内存储数据
- 如何理解句子的生命周期始于对e的评估
- 它解决了什么问题,对于非真空初始化,生命周期在初始化之前就开始了
- Go/C++gRPC客户端通道和存根生命周期
- 如何将"this"的生命周期移动到C++中的另一个对象中?
- 是否可以通过使用移动/交换 c++11 来延长返回的临时变量的生命周期
- 使用对象的生命周期作为设置器的安全性
- 临时人员的生命周期传递给函数
- 我想知道在构造函数中初始化变量时的生命周期
- Lua 用户数据生命周期管理
- 如何使用 epoll(void* event.data.ptr) 管理 Connection 的生命周期
- C++引用的生命周期
- 在堆栈上有一个对象,而不是在函数的整个生命周期内
- 在 Boost ASIO 服务器中处理生命周期
- C++ lambda 生命周期
- 使用互斥锁跟踪另一个应用的生命周期
- QSharedPointer 或 std::shared_ptr 的生命周期
- 来自async_resolve的 boost::asio::ip::tcp::resolver::iterator 的生命周期是多久?
- 如何调整属于类的唯一指针的字符数组的大小.它必须在程序的整个生命周期中保持活力
- 延长 std::tuple<int&,int> 的生命周期,方法是将其分配给 const std::tuple<int, int>&