c++ - 理解左值到右值转换的例子

标签 c++ language-lawyer c++14 constexpr lvalue-to-rvalue

我很难理解这段代码(来自 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/

相关文章:

c++ - 检测字段或成员getter是否为主键的技术

c++ - 返回 *&object 时是否允许复制/移动省略?

c++ - 参数包、捕获子句和初始值设定项

Android OpenCV 并行化循环

c++ - c++中链表和树程序的内存管理

c++ - while(file_object) 是一个导致无限循环的原因

c++ - (int32_t) 255 << 24 是 gcc (C++11) 中的未定义行为吗?

c++ - 在早期检测成语实现中使用 void 模板参数

C++ 入门(第 5 版)和 C++14

c++ - g++ 不允许在 lambda 中通过引用对 const 对象进行广义捕获?