引用相对于其目标的生命周期 [英] The lifetime of a reference with regard to its target

查看:33
本文介绍了引用相对于其目标的生命周期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了阻止我最近给出的答案的评论中的争论,我想要一些对以下问题的建设性回答:

  1. 引用的生命周期与它所引用的对象不同吗?引用仅仅是其目标的别名吗?
  2. 引用能否在格式良好的程序中比其目标存活时间更长,而不会导致未定义的行为?
  3. 如果重用为原始对象分配的存储空间,是否可以进行引用以引用新对象?
  4. 以下代码是否在不调用未定义行为的情况下演示了上述要点?

Ben Voigt 的示例代码并简化(在 ideone.com):

#include #include <new>构造一些东西{国际我;};int main(void){字符缓冲区[sizeof (something) + 40];某物* p = 新(缓冲)某物;p->i=11;内部&寿命 = p-> i;std::cout <<寿命<<"\n";p->~something();//p->i 与其父对象一起死亡新 (p) 字符 [40];//内存被重用,*p(和 p->i)的生命周期就这样完成了new (&outlives) int(13);std::cout <<寿命<<"\n";//但引用仍然有效//并且很有用,因为严格的别名被尊重}

解决方案

引用的生命周期与它所引用的对象不同吗?引用仅仅是其目标的别名吗?

引用有自己的生命周期:

int x = 0;{内部&r = x;}//r 现在死了x = 5;//x 还活着

ref-to-const 还可以延长其裁判的生命周期:

int foo() { return 0;}const int&r = foo();//注意,这不是对局部变量的引用cout<<r;//有效的;foo() 结果的生命周期被延长

尽管这并非没有警告:

<块引用>

对 const 的引用仅在引用 a) 本地且 b) 绑定到其评估创建所述临时对象的纯右值时才延长临时对象的生命周期.(因此它不适用于成员或绑定到 xvalues 的本地引用.)此外,非常量 rvalue 引用以完全相同的方式延长生命周期.[@FredOverflow]

<小时><块引用>

引用能否在格式良好的程序中比其目标存活时间更长,而不会导致未定义的行为?

当然,只要你不使用它.

<小时><块引用>

如果为原始对象分配的存储被重用,是否可以进行引用以引用新对象?

是的,在某些情况下:

<块引用>

[C++11: 3.8/7]: 如果在一个对象的生命周期结束之后,并且在该对象占用的存储空间被重用或释放之前,一个新的对象在原始对象占用的存储位置、指向原始对象的指针、引用原始对象的引用或原始对象的名称object 将自动引用新对象,并且一旦新对象的生命周期开始,可用于操作新对象,如果:

  • 新对象的存储与原始对象占用的存储位置完全重叠,并且
  • 新对象与原始对象的类型相同(忽略顶级 cv 限定符),并且
  • 原始对象的类型不是 const 限定的,并且,如果是类类型,则不包含任何类型为 const 限定或引用类型的非静态数据成员,并且
  • 原始对象是 T 类型的最派生对象 (1.8),而新对象是 T 类型的最派生对象(即,它们不是基类子对象).

<小时><块引用>

以下代码是否在不调用未定义行为的情况下演示了上述要点?

Tl;博士

In order to stem the argument going on in the comments of an answer I gave recently, I'd like some constructive answers to the following questions:

  1. Is a reference's lifetime distinct from the object it refers to? Is a reference simply an alias for its target?
  2. Can a reference outlive its target in a well-formed program without resulting in undefined behaviour?
  3. Can a reference be made to refer to a new object if the storage allocated for the original object is reused?
  4. Does the following code demonstrate the above points without invoking undefined behaviour?

Example code by Ben Voigt and simplified (run it on ideone.com):

#include <iostream>
#include <new>

struct something
{
    int i;
};

int main(void)
{
    char buffer[sizeof (something) + 40];
    something* p = new (buffer) something;
    p->i = 11;
    int& outlives = p->i;
    std::cout << outlives << "\n";
    p->~something(); // p->i dies with its parent object
    new (p) char[40]; // memory is reused, lifetime of *p (and p->i) is so done
    new (&outlives) int(13);
    std::cout << outlives << "\n"; // but reference is still alive and well
                                   // and useful, because strict aliasing was respected
}

解决方案

Is a reference's lifetime distinct from the object it refers to? Is a reference simply an alias for its target?

A reference has its own lifetime:

int x = 0;
{
   int& r = x;
}      // r dies now
x = 5; // x is still alive

A ref-to-const additionally may extend the lifetime of its referee:

int foo() { return 0; }
const int& r = foo();   // note, this is *not* a reference to a local variable
cout << r;              // valid; the lifetime of the result of foo() is extended

though this is not without caveats:

A reference to const only extends the lifetime of a temporary object if the reference is a) local and b) bound to a prvalue whose evaluation creates said temporary object. (So it doesn't work for members, or local references which are bound to xvalues.) Also, non-const rvalue references extend the lifetime in the exact same fashion. [@FredOverflow]


Can a reference outlive its target in a well-formed program without resulting in undefined behaviour?

Sure, as long as you don't use it.


Can a reference be made to refer to a new object if the storage allocated for the original object is reused?

Yes, under some conditions:

[C++11: 3.8/7]: If, after the lifetime of an object has ended and before the storage which the object occupied is reused or released, a new object is created at the storage location which the original object occupied, a pointer that pointed to the original object, a reference that referred to the original object, or the name of the original object will automatically refer to the new object and, once the lifetime of the new object has started, can be used to manipulate the new object, if:

  • the storage for the new object exactly overlays the storage location which the original object occupied, and
  • the new object is of the same type as the original object (ignoring the top-level cv-qualifiers), and
  • the type of the original object is not const-qualified, and, if a class type, does not contain any non-static data member whose type is const-qualified or a reference type, and
  • the original object was a most derived object (1.8) of type T and the new object is a most derived object of type T (that is, they are not base class subobjects).


Does the following code demonstrate the above points without invoking undefined behaviour?

Tl;dr.

这篇关于引用相对于其目标的生命周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆