C++ 理解左值到右值转换示例

C++ 理解左值到右值转换示例,c++,language-lawyer,c++14,constexpr,lvalue-to-rvalue,C++,Language Lawyer,C++14,Constexpr,Lvalue To Rvalue,我很难理解这段代码(来自C++14标准草案[conv.lval]的示例)如何调用g(false)的未定义行为。为什么constexpr使程序有效 另外,“不访问y.n”是什么意思?在对g()的两个调用中,我们都返回n数据成员,那么为什么最后一行说它不访问它呢 结构{int n;}; 自动f(){ sx{1}; constexpr S y{2}; return[&](boolb){return(b?y:x).n;}; } 自动g=f(); int m=g(假);//由于x.n在其外部访问而导致的未

我很难理解这段代码(来自C++14标准草案[conv.lval]的示例)如何调用
g(false)
的未定义行为。为什么
constexpr
使程序有效

另外,“不访问
y.n
”是什么意思?在对
g()
的两个调用中,我们都返回
n
数据成员,那么为什么最后一行说它不访问它呢

结构{int n;}; 自动f(){ sx{1}; constexpr S y{2}; return[&](boolb){return(b?y:x).n;}; } 自动g=f(); int m=g(假);//由于x.n在其外部访问而导致的未定义行为 //一生 int n=g(真);//好的,不访问y.n
这是因为
y.n
未使用odr,因此不需要访问
y.n
odr的使用规则在
3.2
中介绍,并说明:

除非应用 从左值到右值的转换(4.1)到x产生一个不调用任何非平凡函数的常量表达式(5.19) 函数,如果x是对象,则ex是表达式e的潜在结果集的元素,其中 左值到右值的转换(4.1)应用于e,或者e是一个废弃的值表达式

注意,Ben Voigt发表了一些有用的评论,澄清了这一点。因此,这里的工作假设是x为:

y
而e将是(第3.2节第2段涵盖了定义e的不同表达式):

y
生成一个常量表达式,并将左值到右值的转换应用于表达式e

由于
f
生成一个lambda,该lambda通过引用捕获
f
的局部变量
x
一旦调用
f
就不再有效,因为
x
f
中的一个自动变量。由于
y
是一个常量表达式,它的行为就好像没有访问
y.n
,因此我们没有相同的生存期问题

您的示例包含在章节
4.1
[conv.lval]中,在该示例之前,它说:

将左值到右值的转换应用于表达式e时

并包括examle所属的以下项目符号:

e的评估结果是对e的潜在结果集的成员ex的评估,以及 ex命名了一个变量x,该变量x不是ex(3.2)使用的odr

然后:

未访问引用对象中包含的


这适用于C++14标准草案,原因是。

我猜
constexpr
在编译时进行计算,并存储在程序的某个只读部分,与堆栈帧无关,而
x
在堆栈帧中,在堆栈帧被删除后访问它会导致未定义的行为。您在哪里找到这个示例?在标准中,还是其他来源?@BenVoigt它来自C++14[conv.lval]/2.2.@BenVoigt您的评论非常有用。实际上,我刚刚开始深入研究ODR规则,因为最近w.r.t向constexpr和ODR提出了一些与我有关的问题。相对较新的措辞并不直截了当,仅有的一些解释也不是很好。@ShafikYaghmour:是的,我真的不喜欢“表达式的潜在结果”这个术语,它与同一表达式的“结果”完全无关。什么叫“引用对象中包含的值未被访问”?
2
y.n
的值,这是否意味着我不从
g(true)
返回
2
?您确实从
g(true)
返回2,但程序不必访问名为
y.n
的物理内存位置来获取该值。
(b ? y : x).n