将类型为“int”的临时对象转换为引用安全吗?
Is casting a temporary with type `int` to a reference safe?
在以下程序中:
int Func()
{
int a = { 10 };
return a;
}
int main()
{
int& r = (int&)(const int&)Func();
r = 5;
}
r
是对 int
类型临时对象的引用。但是临时对象会立即被销毁,除非它们通常被分配给一个引用。上面的分配似乎不正常。在标准 C++ 中使用 r
安全吗?
简介: C 风格的转换等同于 (C++17 [expr.cast]):
int& r = const_cast<int&>( static_cast<const int&>(Func()) );
在子表达式 static_cast<const int&>(Func())
中,行为由 C++17 [expr.static.cast]/4 描述(其中 T
是要转换为的类型):
If T
is a reference type, the effect is the same as performing
the declaration and initialization T t(e);
for some invented temporary variable t
(11.6) and then using the temporary variable as the result of the conversion
在本例中T
是const int&
,所以引用的初始化类似于const int& t(Func());
。
这段代码现在有两个问题:
- 临时文件的类型
- 涉及的临时对象的生命周期
临时的类型是const int
(C++17 [dcl.init.ref]/5.2.1.2)。因此,您的代码通过修改 const 对象导致未定义的行为。 Link to other SO question on this topic
对于此答案的其余部分(解决生命周期问题),我假设您将 r = 5
更改为仅显示 r
.
的语句
引用链接的行为随着 CWG 1299 的应用而改变。该缺陷于 2011 年 4 月提交,并于 2017 年 3 月解决。该解决方案未出现在 C++17 (N4659) 中;它只出现在 post-C++17 草稿中。
该决议的状态为 DRWP,我的理解是这意味着它追溯适用于 C++17 但不适用于 C++14(如果有人想确认或更正这一点,那就太好了)。
无论如何,此解决方案在某些情况下可以延长引用链的生命周期。写法是(N4762 class.temporary/6):
[...] The temporary object to which the reference is bound or the temporary object that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference if the glvalue to which the reference is bound was obtained
through one of the following:
- [...]
- a
const_cast
, static_cast
, dynamic_cast
, or reinterpret_cast
converting, without a user-defined conversion, a glvalue operand that is one of these expressions to a glvalue that refers to the object designated by the operand, or to its complete object or a subobject thereof,
在 CWG1299 之前,本段仅适用于从纯右值初始化引用,但现在如果指定对象是临时对象,它可以适用于从任何表达式类别初始化引用的情况。
请注意,临时物化 在 C++17 中的工作方式是,当物化发生时,prvalue 被转换为一个 xvalue,这个 xvalue 是 glvalue 所引用的上面的粗体文字。
现在甚至包括一个例子来证实这一点:
const int& b = static_cast<const int&>(0);
// temporary int has same lifetime as b
另一个已删除的答案中显示的编译器行为必须应用 CWG1299 的决议。
在以下程序中:
int Func()
{
int a = { 10 };
return a;
}
int main()
{
int& r = (int&)(const int&)Func();
r = 5;
}
r
是对 int
类型临时对象的引用。但是临时对象会立即被销毁,除非它们通常被分配给一个引用。上面的分配似乎不正常。在标准 C++ 中使用 r
安全吗?
简介: C 风格的转换等同于 (C++17 [expr.cast]):
int& r = const_cast<int&>( static_cast<const int&>(Func()) );
在子表达式 static_cast<const int&>(Func())
中,行为由 C++17 [expr.static.cast]/4 描述(其中 T
是要转换为的类型):
If
T
is a reference type, the effect is the same as performing the declaration and initializationT t(e);
for some invented temporary variablet
(11.6) and then using the temporary variable as the result of the conversion
在本例中T
是const int&
,所以引用的初始化类似于const int& t(Func());
。
这段代码现在有两个问题:
- 临时文件的类型
- 涉及的临时对象的生命周期
临时的类型是const int
(C++17 [dcl.init.ref]/5.2.1.2)。因此,您的代码通过修改 const 对象导致未定义的行为。 Link to other SO question on this topic
对于此答案的其余部分(解决生命周期问题),我假设您将 r = 5
更改为仅显示 r
.
引用链接的行为随着 CWG 1299 的应用而改变。该缺陷于 2011 年 4 月提交,并于 2017 年 3 月解决。该解决方案未出现在 C++17 (N4659) 中;它只出现在 post-C++17 草稿中。
该决议的状态为 DRWP,我的理解是这意味着它追溯适用于 C++17 但不适用于 C++14(如果有人想确认或更正这一点,那就太好了)。
无论如何,此解决方案在某些情况下可以延长引用链的生命周期。写法是(N4762 class.temporary/6):
[...] The temporary object to which the reference is bound or the temporary object that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference if the glvalue to which the reference is bound was obtained through one of the following:
- [...]
- a
const_cast
,static_cast
,dynamic_cast
, orreinterpret_cast
converting, without a user-defined conversion, a glvalue operand that is one of these expressions to a glvalue that refers to the object designated by the operand, or to its complete object or a subobject thereof,
在 CWG1299 之前,本段仅适用于从纯右值初始化引用,但现在如果指定对象是临时对象,它可以适用于从任何表达式类别初始化引用的情况。
请注意,临时物化 在 C++17 中的工作方式是,当物化发生时,prvalue 被转换为一个 xvalue,这个 xvalue 是 glvalue 所引用的上面的粗体文字。
现在甚至包括一个例子来证实这一点:
const int& b = static_cast<const int&>(0);
// temporary int has same lifetime as b
另一个已删除的答案中显示的编译器行为必须应用 CWG1299 的决议。