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.nodr-used ではないため、y.nodr-use のルールへのアクセスを必要とせず、次のように説明されているためです3.2

名前が潜在的に評価される式 ex として表示される変数 xは、左辺値から右辺値への変換 (4.1) を x に適用して、重要な関数を呼び出さない定数式(5.19) を生成しない限り、odr で使用されます。 x はオブジェクト、 ex は式 e の潜在的な結果のセットの要素です。ここで 、左辺値から右辺値への変換 (4.1) が eに適用されるか、 e が破棄された値の式です。

Ben Voigt が、これを少し明確にする有益なコメントをしたことに注意してください。したがって、ここでの作業仮定は、xが次のようになるということです。

y

eは次のようになります ( e が定義されている別の式については、セクション 3.2 のパラグラフ 2 で説明されています)。

(b ? y : x).n

y定数式を生成し、左辺値から右辺値への変換が式eに適用されます。

参照によって のローカル変数fを取得するラムダを生成するので、は内部の自動変数であるため、 への呼び出しが完了すると有効ではなくなります。は定数式であるため、アクセスされていないかのように動作するため、同じ寿命の問題はありません。fxfxfyy.n

あなたの例はN3939セクション4.1 [conv.lval]に含まれており、その例の直前に次のように書かれています:

左辺値から右辺値への変換が式 e に適用され、次のいずれかの場合

例が属する次の箇条書きが含まれます。

e の評価は、e の潜在的な結果のセットのメンバー ex の評価をもたらし、ex は、exによってODR 使用されない変数 x を指定します(3.2)。

それから:

参照されたオブジェクトに含まれる値はアクセスされませ

これは、欠陥レポート 1773により、C++14 ドラフト標準に適用されました。

于 2015-02-13T18:41:20.747 に答える