Unionsのブレースまたは等視化装置
-
20-12-2019 - |
質問
共用体の最大1つの非静的データメンバーには、ブレースまたは等能力がある可能性があります。
しかし
struct Point {
Point() {}
Point(int x, int y): x_(x), y_(y) {}
int x_, y_;
};
union U {
int z;
double w;
Point p = Point(1,2);
};
#include <iostream>
int main () {
U u;
std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
}
.
予想される4196960:0
の代わりに1:2
を印刷します。
これはコンパイラのバグを考えます。それはとても?
解決
C ++ 11 [Class.Clase] / 5状態:
default classのためのコンストラクタは、引数なしで呼び出すことができるClass
X
のコンストラクタです。 ClassX
のユーザー宣言コンストラクタがない場合、パラメータを持たないコンストラクタはデフォルトで暗黙的に宣言されます(8.4)。暗黙的に宣言されたデフォルトコンストラクタは、そのクラスのX
メンバーです。 Classinline public
のデフォルトのデフォルトコンストラクタは、次の場合に削除済みとして定義されています。
- を持つバリアントメンバーを持つ共用体のようなクラスです。
X
は、単語以外のデフォルトコンストラクタ- brace-or-i-iinitizer を持つ静的な非静的データメンバーは参照型、
- brace-or-i-iinitizer のないconst-repended型(またはその配列)の非バリアント非静的データメンバーに、ユーザーに提供されたデフォルトコンストラクタがありません。李>
- のすべてです。
X
は共用体であり、そのすべてのバリアントメンバーはconst-aged型(またはその配列)、- です。
X
は非共用体クラスであり、匿名ユニオンメンバーのすべてのメンバーはconst-aged型(またはその配列)、- 任意の直接または仮想基本クラス、または brace-or-iinitizer を持つ非静的データメンバには、クラスタイプ
から削除されていない関数またはアクセスできない関数にも発生します。X
(またはその配列)があり、M
にはデフォルトのコンストラクタがありません。M
のデフォルトのコンストラクタに適用されるオーバーロード解決(13.3)は、デフォルトのデフォルトコンストラクタまたはデフォルトのデフォルトコンストラクター、または- 任意の直接または仮想基本クラスまたは非静的データメンバーには、デフォルトのデフォルトコンストラクターから削除された、またはアクセスできないデストラクタとの型があります。
既定のコンストラクタは、ユーザーが指定していない場合は些細なコンストラクタです。
- そのクラスには仮想関数(10.3)がない(10.3)、仮想基本クラス(10.1)、
- クラスの非静的データメンバーはブレースまたは等演算子を持ち、
- クラスのすべての直接基本クラスは簡単なデフォルトコンストラクタ、
を持っています- クラスタイプ(またはその配列)のクラスのすべての非静的データメンバーに対して、そのような各クラスには簡単なデフォルトコンストラクタがあります。
それ以外の場合、デフォルトのコンストラクタは非些細なです。
OP内のStruct M
では非自明のデフォルトコンストラクタがありますので、
Point() {}
.
Point
のメンバーを含む共用体のデフォルトのデフォルトコンストラクタは、最初の箇条書きに従って削除されるように定義されます。
- を持つバリアントメンバーを持つ共用体のようなクラスです。
Point
は、単語以外のデフォルトコンストラクタ
は、OPが誤って形成されているプログラムを提示した。
しかし、委員会は、コアワーキンググループ問題1623 :
ユーザー提供のコンストラクタを必要としていることは、理にかなっていないデザインパターンを強制しています。同じ行に沿って、メンバーが自明のデストラクタがあるため、デフォルトのデストラクタが削除されたと定義されているのはなぜですか。 UNIONにユーザー提供のコンストラクタも持っている場合にのみ適用されている場合は、この制限に同意するでしょう。12.1 [Class.Class]段落5、
に準拠クラスX用のデフォルトのデフォルトコンストラクタは、以下の場合に削除済みとして定義されています。
- です。
X
は、単語以外のデフォルトコンストラクターを持つバリアントメンバーを持つ共用体のようなクラス、...
- のものです。
X
は共用体であり、そのすべてのバリアントメンバーはConst認定型(またはその配列)、- です。
X
は非共用体クラスであり、匿名ユニオンメンバーのすべてのメンバーはConst認定の型(またはその配列)、...
非静的データメンバの初期化装置の存在は、 Mem-Initializer の道徳的に相当するため、これらの規則は、生成されたコンストラクタを削除されたときにUnionメンバーがあるときに定義しないように変更されるべきです。非静的データメンバのイニシャライザ。 (9.5 [Class.Union]の段落2-3および7.1.6.1 [DCL.TYPE.CV]の非規範的な参照は、この制限が変更された場合にも更新する必要があるパラグラフ2の段落2の非規範です。)
組合中のすべてのメンバーが構成不可能な型を持っている場合、非静的データメンバのイニシャライザまたはユーザー提供のコンストラクタのいずれかを必要とする9.5 [Class.Union]に要件を追加することも役立ちます。
より一般的な注意事項は、メンバーに自明でないデフォルトコンストラクタがあるため、デフォルトのコンストラクタが削除されたのですか? Union自体はどのメンバーがアクティブなものであるかわからず、デフォルトの構造はメンバーを初期化しません(no ブレースまたは等能力を仮定する)。アクティブメンバーの有効期間を管理するための組合の「所有者」次第です。
発行1623には、委員会がおそらく問題があると考えているというステータス「Drafting」があります。このような Brace-またはInitializer がユニオンメンバーのためにを許可することを示していますか? - しかし、解像度の適切な表現を決定する時間をまだ献身的ではありません。確かに、段落は現在のC ++ 14ドラフトN3936([Class.Cluctor] / 4)において大きく同じです。より簡単な「潜在的に構築されたサブオブジェクト」
両方のコンパイラの動作は厳密に適合していませんが、聖書は標準の精神で行動することを検討します。 GCCは、削除されたデフォルトコンストラクタと brace-or-iinitializer :
の組み合わせによって混乱しているように見えます。- それはの診断不在下でプログラムを診断するブレースまたは等能力 、
main.cpp: In function 'int main()':
main.cpp:17:39: warning: 'u.U::p.Point::y_' is used uninitialized in this function [-Wuninitialized]
std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
^
main.cpp:17:22: warning: 'u.U::p.Point::x_' is used uninitialized in this function [-Wuninitialized]
std::cout << u.p.x_ << ":" << u.p.y_ << std::endl;
^
GCCは、標準に準拠していて、プログラムをILL形成されたとして診断したり、CLANGの振る舞いをエミュレートしたり、 BRANCEまたはEQUALISIZER から適切なコンストラクタを生成したりする必要があります。