4

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

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

struct S { int n; };
auto f() {
    S x { 1 };
    constexpr S y { 2 };
    return [&](bool b) { return (b ? y : x).n; };
}
auto g = f();
int m = g(false); // undefined behavior due to access of x.n outside its
                  // lifetime
int n = g(true);  // OK, does not access y.n
4

1 回答 1

8

这是因为y.n不是 odr-used,因此不需要访问y.nodr-use 的规则,其中包括3.2

变量 x 其名称显示为潜在求值表达式 ex是 odr-used 除非将左值到右值转换 (4.1) 应用到 x产生一个不调用任何非平凡函数的常量表达式 (5.19) 并且,如果x 是一个对象,ex 是表达式 e 的一组潜在结果的元素,其中 左值到右值转换 (4.1) 应用于 e,或者 e 是丢弃值表达式

请注意,Ben Voigt 做了一些有用的评论,稍微澄清了这一点。所以这里的工作假设是x将是:

y

并且e将是(定义 e 的不同表达式包含在第 3.2 节的第 2 段中):

(b ? y : x).n

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

由于f产生一个f通过引用捕获局部变量的 lambdax在调用完成后不再有效,f因为x它是内部的自动变量f。由于y是一个常量表达式,它的行为就像没有y.n被访问一样,因此我们没有相同的生命周期问题。

您的示例包含在N3939部分4.1 [conv.lval]中,并且在该示例之前它说:

当左值到右值的转换应用于表达式 e 时,并且

并包括该示例所属的以下项目符号:

对 e 的评估导致对 e 的一组潜在结果的成员 ex 的评估,并且 ex 命名一个变量 x,该变量 x未被ex (3.2) 使用,

然后:

被引用对象中包含的值未被访问

由于缺陷报告 1773,这已应用于 C++14 草案标准。

于 2015-02-13T18:41:20.747 回答