我很难理解这段代码(来自 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
最佳答案
这是因为y.n
未使用 ODR,因此不需要访问 y.n
3.2
中涵盖了 ODR 使用规则并说:
A variable x whose name appears as a potentially-evaluated expression ex is odr-used unless applying the lvalue-to-rvalue conversion (4.1) to x yields a constant expression (5.19) that does not invoke any non-trivial functions and, if x is an object, ex is an element of the set of potential results of an expression e, where either the lvalue-to-rvalue conversion (4.1) is applied to e, or e is a discarded-value expression
请注意,Ben Voigt 发表了一些有用的评论,稍微澄清了这一点。所以这里的工作假设是 x 将是:
y
和e 将是(定义 e 的不同表达式包含在第 3.2 节的第 2 段中):
(b ? y : x).n
y
产生常量表达式,左值到右值的转换应用于表达式 e。
自 f
产生一个捕获 f
的 lambda的局部变量引用 x
一旦调用 f
就不再有效自 x
以来完成f
里面是一个自动变量.自 y
是一个常量表达式,它的作用就好像y.n
未被访问,因此我们没有相同的生命周期问题。
您的示例包含在 N3939 中节4.1
[conv.lval] 在那个例子之前它说:
When an lvalue-to-rvalue conversion is applied to an expression e, and either
并包含考试所属的以下项目符号:
the evaluation of e results in the evaluation of a member ex of the set of potential results of e, and ex names a variable x that is not odr-used by ex (3.2),
然后:
the value contained in the referenced object is not accessed
由于 defect report 1773,这适用于 C++14 标准草案.
关于c++ - 理解左值到右值转换的例子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28506342/