union ">共用体

Note

C++ 17 以降では、は、 std::variantclass a 共用体のタイプセーフな代替です

A = "no loc" dir = "ltr" lang = "en-us" >union はユーザー定義型で、すべてのメンバーが同じメモリ位置を共有します。 この定義は、任意の時点で、a 共用体に、 メンバーの一覧から1つ以上のオブジェクトを含めることができないことを意味します。 また、メンバー a 共用体に は、常に最大のメンバーを格納するのに十分なメモリのみが使用されることを意味します。

A 共用体は、 多数のオブジェクトがあり、メモリが限られている場合にメモリを節約するために役立ちます。 ただし、a 共用体を 使用するには、特別な注意が必要です。 自分が割り当てたのと同じメンバーに常にアクセスできるようにする責任があります。 いずれかのメンバー型に自明でない " 構造体またはが含まれている場合は 、追加のコードを記述して、明示的に 構造体を破棄し、そのメンバーを破棄する必要があり ます。 共用体を使用する前に 、解決しようとしている問題を、基本 class 型と派生型を使用してより適切に表現できるかどうかを検討してください class 。

構文

= "no loc" dir = "ltr" lang = "en-us" >union tag{member-list};

パラメーター

tag
共用体に指定された型名

member-list
共用体のメンバーは、を 含むことができます。

union ">Declare a union

A union の宣言を開始するには < span=""> = "no loc" dir = "ltr" lang = "en-us" >union キーワードを使用し、 メンバーリストを中かっこで囲みます。

class  = "lang-cpp" >//declaring_a_ 共用体  です。 cpp Union  RecordType//Declare a simple union  型 {char ch; int i; long l; float f; double d; int * int_ptr;}; int main () {RecordType t; t. i = 5;//t では int t. f = 7.25;//t は float を保持します。} 

union ">使用 a union

前の例では、 共用体にアクセスするすべてのコードで、 どのメンバーがデータを保持しているかを把握している必要があります。 この問題の最も一般的な解決策は、 判別 = "no loc" dir = "ltr" lang = "en-us" >union と呼ばれ ます。 このメソッドは、= "no loc" dir = " 共用体 を、 構造体に囲みます。とには、= "no loc" dir = 列挙型メンバーが含まれています。これは、 現在、 共用体に格納されているメンバー型を示し ます。 次の例に、基本的なパターンを示します。

class  = "lang" >#include <> 名前空間 std enum class WeatherDataType {気温, 風力}; 構造体  tempdata {Int ステーション id; time_t 時刻; double 現在の倍精度; double max;}; 構造体  WindData {Int ステーション id; time_t 時刻; int speed;}; 構造体の  入力 {WeatherDataType type; union  {tempdata temp;WindData 風;};};データ型に固有の関数 void Process_Temp (TempData t) {} void Process_Wind (WindData w) {} void Initialize (std:: queue < 入力入力 >& ) {input first; First. type = WeatherDataType:: 気温; first. Temp = {101, 1418855664, 91.8, 108.5, 67.2}; Input. push (first);入力秒。second. type = WeatherDataType:: 風力;second. 風力 = {204, 1418859354, 14, 27};入力。プッシュ (秒) です。} int main (int argc, char * argv []) {//コンテナーすべてのデータレコードキュー < 入力入力 > ;Initialize (入力);while (! WeatherDataType ()) {Input const i = input. front (); switch (i. type) {case:: 気温: Process_Temp (i. Temp); break; case WeatherDataType:: 風力: Process_Wind (); break; default: break;} input. pop ();} は0を返します。}

前の例では、= "no loc" dir = "ltr" lang = "en-us" >union in = "no loc" dir = "ltr" lang < span="">Input構造体には 名前がありません。そのため、union と呼ばれ ます。 そのメンバーは、 構造体のメンバーであるかのように、直接アクセスでき ます。 Anonymous 共用体を使用する方法の詳細については、「」を参照してください。 < span=""> = "no loc" dir = "ltr" lang = "en-us" >共用体 s "linktype =" 自己ブックマーク ">anonymous union セクションを参照してください)。

前の例は、共通の基本クラスから派生した型を使用して解決できる問題を示して classclass います。 コンテナー内の各オブジェクトのランタイム型に基づいてコードを分岐することができます。 コードの保守と理解は簡単ですが、 共用体を使用するよりも時間がかかることがあり ます。 また、 共用体を使用すると、関連のない 型を格納できます。 A 共用体を使用すると、格納されている 値の型を動的に変更することができます。これには、 共用体変数自体の型を変更する必要があり ます。 たとえば、 MyUnionType さまざまな型の異なる値を格納する要素を持つ、の異種配列を作成できます。

この Input構造体を誤用するのは簡単です 。 データを保持するメンバーにアクセスするには、識別子を正しく使用する必要があります。 共用体を作成 private し、特殊なアクセス関数を提供することで、誤用を防ぐことができます。

union -">無制限 共用体 (c++ 11)。

C++ 03 以前では、a 共用体には、 型を持つ非データメンバーを含めることができます。 static 型に class ユーザーが指定した con 構造体の 場合、de 構造体の or 代入演算子。 C++11 では、これらの制限が削除されています。 このようなメンバーを 共用体に含めると、 ユーザーによって指定されていない特殊なメンバー関数はコンパイラによって自動的にマークされ deleted ます。 共用体 が anonymous a class または 構造体の内部にある場合は 、または、ユーザーが指定してい class構造体の特別なメンバー関数 は、としてマークされ deleted ます。 このケースを処理する方法を次の例に示します。 共用体のメンバーの1つには 、この特別な処理を必要とするメンバーがあります。

class  = "lang-cpp" >//MyVariant #include < crtdbg.h > #include < 新しい > #include < ユーティリティ > //サンプルオブジェクトと出力 #include <><><> 名前空間 std 構造体  A {A () = default;A (int i, const string & str): num (i)、name (str) {} int num、string name;//...}; 構造体  B {B () = default;B (int i, const string & str): num (i)、name (str) {} int num、string name、vector < int > vec;//...}; 列挙型 class {None, A, B, Integer}; #pragma warning (プッシュ) #pragma warning (disable: 4624) class myvariant {Public: myvariant (): kind_ (Kind:: None) {} Myvariant (kind kind): kind_ (kind) {switch (kind_) {case Kind:: None: Break; case Kind:: a: new ( & a_) A (); break; Case Kind:: B: New ( & b_) B (); break; case kind:: Integer: i_ = 0; break; default: _ASSERT (false) です。改}} ~ MyVariant () {switch (kind_) {case Kind:: None: break; case 種類:: A: a_. ~ A (); break; case Kind:: B: b_. ~ B (); break; case Kind:: Integer: break; default: _ASSERT (false); break;} kind_ = Kind:: None;}MyVariant (const MyVariant & other): kind_ (other.kind_) {switch (kind_) {Case kind:: None: break; case kind:: A: new ( & A_) A (other.a_); break; case 種類:: B: new ( & b_) B (other.b_); Break; case Kind:: Integer: i_ = other.i_; break; default: _ASSERT (false); break;}}MyVariant (MyVariant && other): kind_ (other.kind_) {switch (kind_) {Case kind:: None: break、Case kind:: A: new ( & A_) A (move (other.a_)); break; case kind:: b: new ( & b_) B (move (other.b_)); Break; case Kind:: Integer: i_ = other.i_; break; default: _ASSERT (false); break;} other.kind_ = Kind:: None;}MyVariant & operator = (Const myvariant & other) {if ( & other! = this) {switch (other.kind_) {case Kind:: None: this- > ~ myvariant (); Break; case の種類:: A: * this = other.a_; break; Case 種類:: B: * this = other.b_; break; Case kind:: Integer: * this = other.i_; break; default: _ASSERT (false); Break;}} が返される * this;}MyVariant & operator = (myvariant && other) {_ASSERT (this! = & other); switch (other.kind_) {case Kind:: None: this- > ~ myvariant (); break; Case 種類:: A: * this = move (other.a_); break; Case kind:: B: * this = move (other.b_); break; Case 種類:: Integer: * this = other.i_; break; default: _ASSERT (false); break;} other.kind_ = kind:: None; return * this;}MyVariant (const A & A): kind_ (種類:: a)、a_ (a) {} MyVariant (a && a): Kind_ (kind:: a)、a_ (移動 (A)) {} myvariant & operator = (const a & a) {if (kind_! = kind:: A) {this- > ~ myvariant (); New (this) myvariant (A);} else {a_ = A;} 返される * this;}MyVariant & operator = (a && a) {if (kind_! = kind:: A) {this- > ~ myvariant (); new (This) myvariant (move (a));} else {a_ = move (a);} return * this;}MyVariant (const B & b): kind_ (種類:: b)、b_ (b) {} MyVariant (b && b): Kind_ (種類:: b)、b_ (移動 (B)) {} myvariant & operator = (const b & b) {if (kind_! = kind:: B) {this- > ~ myvariant (); New (this) myvariant (B);} else {b_ = b;} return * this;}MyVariant & operator = (b && b) {if (kind_! = kind:: B) {this- > ~ myvariant (); new (This) myvariant (移動 (b));} else {b_ = 移動 (b);} return * this;}MyVariant (int i): kind_ (Kind:: Integer)、i_ (i) {} MyVariant & operator = (int i) {if (kind_! = kind:: integer) {this- > ~ myvariant (); new (This) myvariant (i);} else {i_ = i;} return * this;}Kind GetKind () const {return kind_;}&Geta () {_ASSERT (kind_ = = kind:: A); return a_;} Const a & geta () const {_ASSERT (kind_ = = kind:: A); return a_;}B & getb () {_ASSERT (kind_ = = kind:: B); 戻り b_;} Const b & getb () const {_ASSERT (kind_ = = kind:: B); return b_;} int & getb () {_ASSERT (Kind_ = = Kind:: integer); return i_;} const int & getb () const {_ASSERT (kind_ = = kind:: integer); 戻り i_;} プライベート: 種類 kind_; 共用体  {A a_;B b_;int i_;};};#pragma warning (pop) int main () {A a (1, "Hello from A");B b (2, "Hello from B");MyVariant mv_1 = a;cout << "mv_1 = a:" << Mv_1。 geta (). name << endl;mv_1 = b;cout << "mv_1 = b:" << Mv_1。 getb (). name << endl;mv_1 = A (3, "hello from A");cout << R "aaa (mv_1 = a (3," hello) "):) aaa" << Mv_1。 geta (). name << endl; mv_1 = 42; cout << "mv_1 = 42:" << mv_1 () << endl;vec = {10, 20, 30, 40, 50};mv_1 = 移動 (b);cout << (移動後、mv_1 = b: vec = " << Mv_1. getb (). vec () << endl;cout << endl << "文字を押す" << endl; char c; cin >> c;}

A 共用体に 参照を格納することはできません。 A 共用体で も継承は ’ サポートしていません。 つまり、 union を ベースとして使用したり、別のデータを継承し classclass たり、仮想関数を使用したりすることはできません。

union ">Initialize a union

< span=""> かっこで囲まれた式を割り当てることにより、同じステートメント内で = "no loc" dir = "ltr" lang = "en-us" >union を宣言して初期化することができます。 式が評価され、 共用体の最初のフィールドに割り当てられ ます。

class  = "lang" <> は名前空間 std を使用して iostream を >#include します。 union  numerictype {Short iValue; 長い左辺値; Double dvalue;}; int main () { union  numerictype 値 = {10};//ivalue = 10 Cout << 値。 ivalue << endl;値。 dValue = 3.1416;cout << 値。 dValue << endl;}/* 出力:10 3.141600 */ 

NumericTypeunion はメモリに配置されます (概念的には)。

Diagram that shows the overlapping storage of data in a numeric type <span <span class=class Diagram that shows the overlapping storage of data in a numeric type <span <span class= = "no loc" dir = "ltr" lang = "en-us" >union . " title = "データの Storage numerictype union " data-linktype = "相対パス"/>
のデータ NumericType共用体

union s "> Anonymous union

Anonymous 共用体 は、またはを使用せずに宣言されてい class-namedeclarator-list ます。

= "no loc" dir = "ltr" lang = "en-us" >union {member-list}

Anonymous 共用体で宣言された名前 は、非メンバー変数のように直接使用されます。 これは、anonymous 共用体で宣言された名前が、 外側のスコープ内で一意である必要があることを意味します。

Anonymous 共用体には、 次の追加の制限が適用されます。

  • ファイルまたは名前空間スコープで宣言されている場合は、としても宣言する必要があり static ます。

  • メンバーだけを含めることができ public ます。 privateprotected anonymous union のメンバーとメンバーは、 エラーを生成します。

  • メンバー関数を持つことはできません。

こちらもご覧ください

クラス es-and- 構造体 s-cpp "linktype =" 相対パス ">クラスと構造体
キーワード
クラス -cpp "linktype =" 相対パス ">class
= "linktype" dir = "ltr" lang = "en-us" >構造体 cpp "data-=" 相対パス ">構造体です。