C++ Academy · レッスン

unionとそのリスク

型間でメモリを共有します

レッスン 2/413 ステップ

「unionとそのリスク」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。

union とは

union を使うと、複数のメンバーで同じメモリを共有できます。一度に有効にできるメンバーは 1 つだけで、union のサイズは最大のメンバーと同じになります。

#include <iostream>
union Number {
    int i;
    float f;
};
int main() {
    Number n;
    n.i = 42;
    std::cout << n.i << "\n";
}

union のサイズ

メンバーは重なって配置されるため、union の sizeof はメンバーの合計ではなく、最大のメンバーのサイズ(およびアラインメント用のパディング)になります。

#include <iostream>
union Mix { char c; int i; double d; };
int main() {
    std::cout << sizeof(Mix) << "\n"; // size of double (often 8)
}

一方に書き込み、別の一方を読み取る

一方のメンバーに書き込み、別のメンバーを読み取ることが、中心的なリスクです。ビットが別の型として解釈されるため、通常は未定義の動作になるか、予想外の結果になります。

#include <iostream>
union Bits { int i; float f; };
int main() {
    Bits b;
    b.f = 1.0f;
    std::cout << b.i << "\n"; // reads float bits as int
}

アクティブにできるメンバーは1つだけ

安全に読み取れるのは、最後に書き込んだメンバーだけです。どのメンバーが「アクティブ」かは、ユニオン自身は記憶しないため、自分で管理してください。

#include <iostream>
union Value { int i; double d; };
int main() {
    Value v;
    v.d = 3.14;        // d is active
    std::cout << v.d << "\n";
}

タグ付きユニオンパターン

ユニオンを安全に使うには、アクティブなメンバーを記録するタグ(enum)と組み合わせます。これはstd::variantの手動実装による先祖にあたります。

#include <iostream>
struct Tagged {
    enum { Int, Double } tag;
    union { int i; double d; };
};
int main() {
    Tagged t; t.tag = Tagged::Int; t.i = 7;
    if (t.tag == Tagged::Int) std::cout << t.i << "\n";
}

正しいメンバーを読み取る

読み取る前に、必ずタグに基づいて分岐してください。間違ったメンバーを読み取ると、無意味な値が生成されます。

#include <iostream>
struct Tagged {
    enum { Int, Double } tag;
    union { int i; double d; };
};
void print(const Tagged& t) {
    if (t.tag == Tagged::Int) std::cout << "int " << t.i << "\n";
    else std::cout << "double " << t.d << "\n";
}
int main() { Tagged t{Tagged::Double}; t.d = 2.5; print(t); }

非自明なメンバー

コンストラクターやデストラクターを持つメンバー(std::stringなど)をユニオンに入れるには、手動で構築と破棄を行う必要があります。これはエラーの原因になりやすく、std::variantを優先するもう1つの理由です。

匿名ユニオン

匿名ユニオンには名前がなく、そのメンバーに直接アクセスします。構造体の内部で便利に使えますが、アクティブなメンバーに関する同じルールが適用されます。

#include <iostream>
struct Packet {
    int kind;
    union { int code; char letter; };
};
int main() {
    Packet p; p.kind = 1; p.code = 99;
    std::cout << p.code << "\n";
}

ユニオンが危険な理由

危険性のまとめ:

  • どのメンバーがアクティブかを記憶しません。
  • アクティブでないメンバーを読み取ると、未定義の動作になります。
  • 非自明な型には、手動でライフタイムを管理する必要があります。

それでもユニオンが役立つ場面

ユニオンは、低レベルの処理では今でも役立ちます。たとえば、バイトの再解釈、組み込みコードでメモリが厳しく制限される場合の節約、固定されたバイナリレイアウトへの対応などです。日常的な「複数の型のうち1つ」を表すデータには、より安全な代替手段を優先してください。

std::variantへ向けて

std::variantは、アクティブな型を自動的に追跡する型安全なユニオンです。間違った型にアクセスすると例外を送出します。このコースの後半では、std::variantについて詳しく学びます。

理解度チェック

ユニオンについての理解を確認しましょう。

まとめ

ユニオンについて、次のことを学びました:

  • すべてのメンバーが1つのメモリ領域を共有します。
  • 読み取れるのは、最後に書き込んだメンバーだけです。
  • タグ(enum)を使って、アクティブなメンバーを追跡します。
  • 現代のC++では、安全性のためにstd::variantを優先します。
無料で開始

AI チューターと学ぶ C++ — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
51
レッスン
203

よくある質問

「unionとそのリスク」レッスンは無料ですか?

はい。「unionとそのリスク」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。

「unionとそのリスク」で何を学びますか?

型間でメモリを共有します ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C++ Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「unionとそのリスク」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC++ Academyレッスンでコードを書いて実行できますか?

はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. スコープ付きenum class
  2. unionとそのリスク
  3. std::variant
  4. std::visit
← C++ Academyに戻る