我知道标准有一个关于延长临时生命周期的例外,基本上说在构造函数中绑定const引用不会延长生命周期,但这是否也适用于文字?例如:
class C {
private:
const int& ref;
public:
C(const int& in)
: ref{in}
{ }
};
如果我有一个函数返回这种类型的对象
C f() {
C c(2);
return c;
}
如果我知道它绑定到字面值,那么c.ref
的值是否会在调用者中未定义?
答案 0 :(得分:6)
否即可。构造函数完成执行后,您将无法使用该引用
当非类型的prvalue绑定到const
- 同一类型的引用时,始终引入临时值。因此,构造函数的参数引用将引用一个在引用超出范围时被销毁的临时文件。在那之后,成员引用是悬空的,并且尝试访问该引用后面的存储值会导致UB。
[dcl.init.ref] / 5:
对类型“ cv1
T1
”的引用由表达式初始化 输入“ cv2T2
”如下:
- 如果引用是左值引用和初始化表达式
- 是左值(但不是位字段),[...]
- 有一个类类型(即
T2
是类类型)[..]否则,引用应为对非易失性
const
类型的左值引用(即 cv1 应为const)或引用 应为右值参考。
如果是初始化表达式
- 是xvalue(但不是位字段),类prvalue,数组prvalue或函数lvalue和[..]
- 有一个班级类型[..]
否则:(5.2.2.1)
- 如果
T1
是班级类型[..]- 如果
T1
是非类型类型,则会创建一个临时类型为“ cv1T1
”并从初始化程序复制初始化(8.5)表达。 然后将引用绑定到临时。
不出所料,整数文字确实是prvalues。 [expr.prim.general] / 1:
字符串文字是左值;所有其他文字都是prvalues。
最后,如果不清楚,[class.temporary] / 5:
引用绑定的临时值或临时值 引用绑定到的子对象的完整对象 在参考文件的生命周期内持续存在,除了:
- 构造函数的ctor-initializer(12.6.2)中的引用成员的临时绑定将持续存在,直到构造函数退出。
答案 1 :(得分:1)
简短回答:评估c.ref
几乎肯定是非法的(调用未定义的行为)。
答案很长: 将引用绑定到整数文字时,您实际执行的操作如下:
整数文字指的是所谓的“a value that is not associated with an object”。
要绑定对它的引用,需要创建一个保持相同值的对象。原因是引用(或指针)必须始终指向一个对象(这反过来只是一点内存)。因此,会创建一个临时对象来保存该值。
只要正在评估它们所创建的表达式,临时对象就会保证一直存在。由于您的对象存在的时间较长,因此保留您的值的临时对象会被提前销毁,并且可能无法再访问该引用。
请注意,如果您在创建c.ref
的表达式中访问c
,您实际上会没事。