6

これは、これらの 質問のフォローアップです。

次のコードを検討してください。

struct A {
private:
    A* const& this_ref{this};
};

int main() {
    A a{};
    (void)a;
}

でコンパイルすると、GCC v6.2 とclang v3.9の-Wextra両方で警告が表示されます。

とにかく、以下に示すわずかに変更されたバージョンでは、動作が異なります。

struct A {
    A* const& this_ref{this};
};

int main() {
    A a{};
    (void)a;
}

この場合、GCCは警告を出さず、clangは前の例で返されたのと同じ警告を出します。

警告はほぼ同じです。
それはclangのものに従います:

3 : 警告: 参照メンバー 'this_ref' を一時的な値 [-Wdangling-field] にバインドしています

どのコンパイラが正しいですか?

この場合、GCC は間違っていると思います。私は問題を提起していましたが、言語の不可解なコーナー ケースのため、逆かもしれません。

4

3 に答える 3

2

メンバー宣言

A* const& this_ref{this};

コンストラクターの実行中にのみ存在する一時への参照をバインドします (注:thisは右辺値式です)。

そのコンテキストで正式に利用できるかどうかthisはわかりませんが、そのポインターを使用している場合は、UB の深刻なケースがあります。

どのコンパイラが正しいですか?

… コンパイラは、必要な数の診断を発行できます。診断書を発行することは間違っていません。したがって、あなたの説明によれば、両方がコードを受け入れると、両方のコンパイラが正しいか (これが最も可能性が高いと思います)、両方が間違っています。

于 2016-09-12T12:11:45.053 に答える
1

thisprvalueであり、参照を prvalue にバインドすると一時オブジェクトが作成されるため、参照メンバーをデフォルトメンバー初期化子の一時にバインドしています。

また、デフォルトのメンバー初期化子で参照メンバーを一時的にバインドするのは形式が正しくありません。これは、標準で明示的に述べられています。

$12.6.2/11 ベースとメンバーの初期化 [class.base.init] :

既定のメンバー初期化子から参照メンバーにバインドされた一時的な式の形式が正しくありません。[ 例:

struct A {
  A() = default;          // OK
  A(int v) : v(v) { }     // OK
  const int& v = 42;      // OK
};
A a1;                     // error: ill-formed binding of temporary to reference
A a2(1);                  // OK, unfortunately

— 終了例 ]

CWG 1696を参照してください。これは C++14 に適用されます。

于 2016-09-12T13:50:31.690 に答える
1

この警告の理由は、標準 (12.2.5) からの IMO の抜粋です。

コンストラクターの ctor-initializer (12.6.2) の参照メンバーへの一時的なバインドは、コンストラクターが終了するまで持続します。

キーワード this は prvalue 式であるため、初期化中this_refに一時が作成され、this_refその一時にバインドされます。

しかし、あなたの参照が実際に で初期化されているかどうかは疑問ctor-initializerです。

あなたが書く場合:

struct A {
private:
    const int& rr = 1+1;
};

次に、gcc でまったく同じ問題を再現します。private を削除すると、この警告も削除されます。

this pointer非静的メンバー関数の本体で使用される可能性があることを私が知っていることから、デフォルトメンバーの初期化中に引数として使用できることを読んだことはありません。

于 2016-09-12T13:40:43.240 に答える