名前空間
変種
操作

switch

From cppreference.com
< cpp‎ | language
 
 
C++言語
全般
フロー制御
条件実行文
if
switch
繰り返し文 (ループ)
for
範囲for (C++11)
ジャンプ文
関数
関数宣言
ラムダ式
inline指定子
動的例外仕様 (C++17まで*)
noexcept指定子 (C++11)
例外
名前空間
指定子
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
記憶域期間指定子
初期化
代替表現
リテラル
ブーリアン - 整数 - 浮動小数点数
文字 - 文字列 - nullptr (C++11)
ユーザー定義 (C++11)
ユーティリティ
属性 (C++11)
typedef宣言
型エイリアス宣言 (C++11)
キャスト
メモリ確保
クラス
クラス固有の関数プロパティ
explicit (C++11)
static

特殊メンバ関数
テンプレート
その他
 
 

条件の値に応じて、複数の文のいずれかに制御を移します。

目次

[編集] 構文

attr (オプション) switch ( init-statement (オプション) condition ) statement
attr - (C++11以降) 任意の数の属性
init-statement - (C++17 以降) 以下のいずれか
  • 式文 (null 文 ; であることもあります)
  • 単純宣言。通常は初期化子付き変数の宣言ですが、任意の数の変数や構造化束縛を宣言できます。
(C++23から)

どのinit-statementもセミコロンで終わらなければならないことに注意してください。これが、しばしば非公式に式または宣言の後にセミコロンが続くと説明される理由です。

condition - 条件
statement - 文 (通常は複合文)

[編集] 条件

conditionまたは単純宣言のいずれかです。

  • 構文的に構造化束縛宣言として解決できる場合、構造化束縛宣言として解釈されます。
(C++26以降)
  • 構文的に式として解決できる場合、式として扱われます。それ以外の場合は、宣言(構造化束縛宣言ではない)(C++26以降)として扱われます。

制御が条件に到達すると、条件は値を生成し、その値を使用して制御がどのラベルに移動するかを決定します。

[編集]

condition が式の場合、生成される値はその式の値です。

[編集] 宣言

condition が単純宣言の場合、生成される値は決定変数 (下記参照) の値です。

[編集] 非構造化束縛宣言

宣言には以下の制限があります

  • 構文的に以下の形式に準拠します
  • type-specifier-seq declarator = assignment-expression
(C++11まで)
  • attribute-specifier-seq(任意) decl-specifier-seq declarator brace-or-equal-initializer
(C++11以降)

宣言の判定変数は、宣言された変数です。

構造化束縛宣言

宣言には以下の制限があります

宣言の判定変数は、宣言によって導入される発明された変数eです。

(C++26以降)

[編集]

condition は以下の型のみを生成できます。

  • 整数型
  • 列挙型
  • クラス型

生成された値がクラス型の場合、それは文脈的に暗黙的に整数型または列挙型に変換されます。

(変換された可能性のある) 型が整数昇格の対象となる場合、生成された値は昇格された型に変換されます。

[編集] ラベル

switch 文内の任意の文には、以下の1つ以上のラベルを付けることができます。

attr (オプション) case constant-expression : (1)
attr (オプション) default: (2)
attr - (C++11以降) 任意の数の属性
定数式 - switch 条件の調整された型の変換された定数式


case または default ラベルは、それを囲む最も内側の switch 文に関連付けられます。

以下のいずれかの条件が満たされる場合、プログラムは不適格です。

  • switch 文が、変換後に同じ値を持つ constant-expression を持つ複数の case ラベルに関連付けられている場合。
  • switch 文が、複数の default ラベルに関連付けられている場合。

[編集] 制御フローの転送

switch 文の条件が (変換された可能性のある) 値を生成するとき

  • 関連付けられた case ラベル定数のいずれかが同じ値を持つ場合、制御は一致する case ラベルでラベル付けされた文に渡されます。
  • そうでない場合、関連付けられた default ラベルがある場合、制御は default ラベルでラベル付けされた文に渡されます。
  • そうでない場合、switch 文内のどの文も実行されません。

case および default ラベル自体は制御フローを変更しません。switch 文の途中から抜けるには、breakを参照してください。

コンパイラは、フォールスルー ( break なしで次の case または default ラベルに到達すること) について警告を発することがあります。ただし、フォールスルーが意図的であることを示すために、属性 [[fallthrough]]case ラベルの直前に現れる場合は除きます(C++17 以降)

switch (1)
{
    case 1:
        std::cout << '1'; // prints "1",
    case 2:
        std::cout << '2'; // then prints "2"
}
switch (1)
{
    case 1:
        std::cout << '1'; // prints "1"
        break;            // and exits the switch
    case 2:
        std::cout << '2';
        break;
}

初期化子付き switch

init-statement が使用される場合、switch 文は以下と同等です。

{
init-statement
switch ( condition ) statement

}

ただし、init-statement によって宣言された名前 (init-statement が宣言の場合) および condition によって宣言された名前 (condition が宣言の場合) は、statement のスコープでもある同じスコープ内にあります。

(C++17以降)

[編集] 注釈

変数のスコープに入る制御の転送は許可されていないため、宣言文が statement 内で検出された場合、それは自身の複合文内でスコープ化される必要があります。

switch (1)
{
    case 1:
        int x = 0; // initialization
        std::cout << x << '\n';
        break;
    default:
        // compilation error: jump to default:
        // would enter the scope of 'x' without initializing it
        std::cout << "default\n";
        break;
}
switch (1)
{
    case 1:
        {
            int x = 0;
            std::cout << x << '\n';
            break;
        } // scope of 'x' ends here
    default:
        std::cout << "default\n"; // no error
        break;
}

[編集] キーワード

switch, case, default

[編集]

以下のコードは、switch 文のいくつかの使用例を示しています。

#include <iostream>
 
int main()
{
    const int i = 2;
    switch (i)
    {
        case 1:
            std::cout << '1';
        case 2:              // execution starts at this case label
            std::cout << '2';
        case 3:
            std::cout << '3';
            [[fallthrough]]; // C++17 attribute to silent the warning on fallthrough
        case 5:
            std::cout << "45";
            break;           // execution of subsequent statements is terminated
        case 6:
            std::cout << '6';
    }
 
    std::cout << '\n';
 
    switch (i)
    {
        case 4:
            std::cout << 'a';
        default:
            std::cout << 'd'; // there are no applicable constant expressions 
                              // therefore default is executed
    }
 
    std::cout << '\n';
 
    switch (i)
    {
        case 4:
            std::cout << 'a'; // nothing is executed
    }
 
    // when enumerations are used in a switch statement, many compilers
    // issue warnings if one of the enumerators is not handled
    enum color { RED, GREEN, BLUE };
    switch (RED)
    {
        case RED:
            std::cout << "red\n";
            break;
        case GREEN:
            std::cout << "green\n";
            break;
        case BLUE:
            std::cout << "blue\n";
            break;
    }
 
    // the C++17 init-statement syntax can be helpful when there is
    // no implicit conversion to integral or enumeration type
    struct Device
    {
        enum State { SLEEP, READY, BAD };
        auto state() const { return m_state; }
 
        /* ... */
 
    private:
        State m_state{};
    };
 
    switch (auto dev = Device{}; dev.state())
    {
        case Device::SLEEP:
            /* ... */
            break;
        case Device::READY:
            /* ... */
            break;
        case Device::BAD:
            /* ... */
            break;
    }
 
    // pathological examples
 
    // the statement does not have to be a compound statement
    switch (0)
        std::cout << "this does nothing\n";
 
    // labels do not require a compound statement either
    switch (int n = 1)
        case 0:
        case 1:
            std::cout << n << '\n';
}

出力

2345
d
red
1

[編集] 欠陥報告

以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。

DR 適用対象 公開された動作 正しい動作
CWG 1767 C++98 整数昇格の対象ではない型の condition は昇格できません
整数昇格できませんでした
昇格しません
これらの型の condition
CWG 2629 C++98 condition は浮動小数点変数の宣言である可能性があります。 禁止された

[編集] 関連項目

[編集] 外部リンク

1.  ダフのデバイスを使用したループアンローリング
2.  ダフのデバイスは C/C++ でコルーチンを実装するために使用できます
English 日本語 中文(简体) 中文(繁體)