C++ 将类型为'int'的临时变量强制转换为引用是否安全?
在以下程序中:C++ 将类型为'int'的临时变量强制转换为引用是否安全?,c++,reference,language-lawyer,object-lifetime,C++,Reference,Language Lawyer,Object Lifetime,在以下程序中: int Func() { int a = { 10 }; return a; } int main() { int& r = (int&)(const int&)Func(); r = 5; } r是对类型为int的临时文件的引用。但是临时表会立即被销毁,除非它们通常被指定为参考。上面的作业似乎不正常。在标准C++中使用 R是否安全?< /P> < P>引言:C样式的转换相当于(C++ 17 [Exp.
int Func()
{
int a = { 10 };
return a;
}
int main()
{
int& r = (int&)(const int&)Func();
r = 5;
}
r
是对类型为int
的临时文件的引用。但是临时表会立即被销毁,除非它们通常被指定为参考。上面的作业似乎不正常。在标准C++中使用<代码> R<代码>是否安全?< /P> < P>引言:C样式的转换相当于(C++ 17 [Exp.Cas]):
int&r=const_cast(static_cast(Func());
在子表达式static\u cast(Func())
中,行为由C++17[expr.static.cast]/4描述(其中T
是要转换到的类型):
如果T
是参考类型,则效果与执行相同
声明和初始化T(e)
对于一些发明的临时变量t
(11.6),然后使用临时变量作为转换的结果
在本例中,T
是const int&
,因此引用的初始化类似于const int&T(Func())代码>
现在这段代码中有两个问题:
- 临时文件的类型
- 所涉及的临时人员的生命周期
临时文件的类型是const int
(C++17[dcl.init.ref]/5.2.1.2)。因此,您的代码通过修改const对象导致未定义的行为
对于这个答案的其余部分(解决生存期问题),我将假设您将r=5
更改为只读取r
的语句
参考链的行为随着应用的改变而改变。该缺陷于2011年4月提交,并于2017年3月解决。分辨率没有出现在C++17(N4659)中;它只出现在C++17之后的草稿中
该决议的状态为DRWP,我的理解是,这意味着它追溯适用于C++17,但不适用于C++14(如果有人想确认或纠正这一点,那就太好了)
无论如何,在某些情况下,此解决方案允许在引用链上进行寿命扩展。措辞为(N4762类临时/6):
[…]如果获得了引用绑定到的gl值,则引用绑定到的临时对象或作为引用绑定到的子对象的完整对象的临时对象将在引用的生命周期内持续存在
通过以下方式之一:
- [……]
常量转换
,静态转换
,动态转换
,或重新解释转换
在无需用户定义转换的情况下,将这些表达式之一的glvalue操作数转换为glvalue,该glvalue引用操作数指定的对象,或其完整对象或其子对象
在CWG1299之前,本段仅适用于从prvalue初始化引用,但现在,如果指定对象是临时对象,则可适用于从任何表达式类别初始化引用的情况
请注意,在C++17中,临时物化的工作方式是在物化发生时将prvalue转换为xvalue,而此xvalue是上面粗体文本所指的glvalue
现在甚至有一个例子证实了这一点:
const int&b=static_cast(0)代码>//临时int与b具有相同的生存期
另一个已删除答案中显示的编译器行为必须应用CWG1299的分辨率。即使生命周期延长,这也是修改常量的UBobject@M.M我在这个程序中没有看到任何常量对象。@当从类型为t
的prvalue初始化const t&
时,在临时对象具体化之前,prvalue被转换为const T
。@nano:我已经删除了我的答案。它需要更多的专业知识来给出一个好的答案。签出:。这是一个老问题(C++11),但它揭示了这个问题。这似乎更复杂(正如您所怀疑的,类型是类还是非类可能很重要)。讨论了生存期问题(标准不清楚通过将prvalue强制转换为引用类型创建的临时对象的生存期),尽管(a)我不清楚DR1376的拟议解决方案实际上是如何解决这个问题的,(b)C++17根本不包含该解决方案,它是一个类型为int
的临时“对象”?我习惯于假设“对象”不是基本类型,而“表达式”可以是基本类型。该子句是关于对象的;为什么不使用表达式
这个词?@nano是的,它是一个类型为const int
的临时对象。您正在考虑类类型的对象和非类类型的对象(后者有时称为内置类型的对象)之间的区别。另外,对象不是表达式,表达式也不是对象。你能给我一个不是表达式的对象的例子吗?@nano所有对象都不是表达式。对象是存在于内存中的东西(在抽象机器中);表达式是源代码中的语法结构
int& r = const_cast<int&>( static_cast<const int&>(Func()) );