web-dev-qa-db-ja.com

関数の呼び出し時に「制御の転送が次の初期化をバイパスする」スイッチ

次のスイッチを作成しようとすると、「制御の転送が初期化をバイパスします:」というエラーが表示されます。

switch (retrycancel)
{
    case 4:    //The user pressed RETRY
        //Enumerate all visible windows and store handle and caption in "windows"
        std::vector<MainHandles::window_data> windows = MainHandles().enum_windows().get_results(); 
        break;

    case 2: 
        //code
}

列挙関数の呼び出しと関係があります。スイッチ内から関数を呼び出すことが許可されていない場合、この種の問題の回避策はありますか?

49
Lumpi

c ++標準のセクション6.6.4:

Gotoステートメントは、無条件に制御を識別子でラベル付けされたステートメントに転送します。識別子は、現在の機能にあるラベル(6.1)でなければなりません。

c ++標準のセクション6.7:

ブロックに転送することは可能ですが、初期化で宣言をバイパスする方法ではありません。自動ストレージ期間を持つローカル変数がスコープ内にないポイントからスコープ内にあるポイントにジャンプするプログラムは、変数がPODタイプ(3.9)を持ち、初期化子なしで宣言されていない限り、不正な形式です。

エンファシス私によって追加されました。 switchは実際にはgotoに変装しているため、この動作に遭遇しています。これを解決するには、switchを使用する必要がある場合は中括弧を追加します

switch (retrycancel)
    {
    case 4:
    {
        const std::vector<MainHandles::window_data> windows(
            MainHandles().enum_windows().get_results()
        );
        break;
    }
    case 2: 
        //code
    }

またはif/elseにリファクタリングします

if (retrycancel == 4) {
    const std::vector<MainHandles::window_data> windows(
        MainHandles().enum_windows().get_results()
    );
} else if (retrycancel == 2)
    // code
} else {
    ...
}

windows内にvectorswitchを作成することで何を達成したいのか、私には明らかではありません。そのため、設計を再考することをお勧めします。 例では変更されていないので、constwindows修飾子を追加しました。

74
Sam Miller

スイッチは基本的にgotoです。つまり、適切なラベルへのgotoです。 C++標準では、gotoが非PODオブジェクトの初期化をバイパスすることを禁止しています。ベクトル宣言を中括弧に入れると、問題が解決します

switch (retrycancel)
    {
     case 4:                //The user pressed RETRY
     {
        std::vector<MainHandles::window_data> windows = MainHandles().enum_windows().get_results(); //Enumerate all visible windows and store handle and caption in "windows"
        break;
     }
    case 2: 
        //code
    }
11
Armen Tsirunyan