"Most important const"条件表达式?
"Most important const" with conditional expression?
考虑以下代码:
int foo(MyClass const* aPtr = 0) {
MyClass const& a = aPtr ? *aPtr : MyClass(); // Either bind to *aPtr, or to a default-constructed MyClass
...
return a.bar();
}
希望这里使用的是"最重要的const"。目的是允许传入一个空的aPtr
(顺便说一句,是的,它必须是一个指针参数),在这种情况下,将默认构造一个临时MyClass
对象,并通过绑定到它的const引用扩展其生存期。然而,如果aPtr
不为空,则引用将绑定到它的指向对象,而不会发生任何(昂贵的)复制构造。
问题二:
- 如果
aPtr == 0
,a
是保证引用一个有效的MyClass
对象,直到函数结束? - 如果是
aPtr != 0
,a
会绑定到它,而不是其他MyClass
吗?
根据测试,对1的答案几乎肯定是"是"。我不太确定,不过(复制省略之类的)…似乎有可能条件表达式最终会从*aPtr
复制构造一个临时的MyClass
,并延长临时的 的寿命。
条件表达式是一个右值(因为它的一个操作数是右值)。如果选择了条件操作符的第一个可选项,则将其转换为临时操作符(这会导致复制)。该临时对象绑定到引用,并应用通常的生命周期扩展。
相关标准[expr.cond]:
如果操作数具有类类型,则结果是结果类型的右值临时值,根据第一个操作数的值从第二个操作数或第三个操作数复制初始化。
对于第一个,是的,a
被保证引用一个有效的MyClass
对象。这直接来自[class.temporary]/4-5:
在两种上下文中,临时变量在fulexpression末尾的不同位置被销毁。第一个上下文是在调用默认构造函数[…]
时。第二个上下文是当引用绑定到临时对象时。引用所指向的临时对象引用被绑定到的子对象的完整对象(即临时对象)持续存在引用的生命周期,除了:
- 在构造函数的参数初始化式[…]
中临时绑定到引用成员- 函数调用中临时绑定到引用参数[…]
- 函数返回语句中临时绑定返回值的生命周期[…]
- 在new-initializer[…]
中临时绑定到引用
这些例外都不适用。
如果aPtr
是一个有效的指针,那么由于aPtr ? *aPtr : MyClass{}
的类型只是MyClass
,因此进行复制。该临时对象被绑定到a
,并且其生命周期也出于同样的原因而持续存在。
关于1)见上面kerek的回答
关于2)标准说关于条件运算符:
5.16/4:如果第二个和第三个操作数是相同值类别的glvalue,并且具有相同类型,则结果为该类型和值类别(…)。
5.16/5:否则,结果为右值。(…)
根据3.10/1中左值和右值的分类,*aPtr
为左值,MyClass()
为右值。因此,结果应该是一个右值,以便引用应该引用这个临时(可能是一个复制构造的temp)。
Edit:这里有一个在线演示,它显示const引用引用的是一个临时对象,而不是aPtr指向的原始对象。
- 优化/减少 if 语句中的条件表达式
- 实现基于数字值(正、负、零)的条件表达式的最佳方法
- C++多个正则表达式条件语法
- 如何使用条件表达式返回对象指针?
- 如何将特征张量的值作为'if'条件表达式
- 变量在常量表达式中可用的条件
- 有条件地忽略 c++11 正则表达式中的大小写
- 对条件表达式结果的赋值(其中第二个和第三个操作数是相同类型和值类别的变量)是否仍然存在?
- 类简单分数的不可接受的条件表达式
- 如何在条件表达式中使用 'cin' 正确退出 while 循环?(C++,CLion)
- 条件表达式解析新表达式中详细阐述的类型说明符时出错
- 逗号(,)在条件部分中两个表达式之间的for循环中的工作方式
- 是“警告 C4127”(条件表达式是常量)曾经有帮助
- 是条件表达式C++总是布尔类型
- 条件断点:此表达式具有副作用,不会计算
- 是否可以将多个关系表达式放入 for 循环的测试条件中
- LAMBDA 错误:类型 'void' 的条件表达式是非法的
- 条件语句在比较表达式时的基础是什么?
- 条件表达式中的右值引用
- 声明不能发生在条件运算符表达式内部