C++におけるプログラミングでは、繰り返し処理(ループ)をいかに効率的かつ読みやすく記述するかが重要です。
ループ制御を行うためのキーワードとして「continue文」は非常に重要な役割を担っています。
特定の条件下で現在の処理をスキップし、次の反復処理へ即座に移行したい場合に活用されます。
本記事では、C++におけるcontinue文の基本的な使い方から、混同されやすいbreak文との違い、実戦で役立つループ制御のテクニックまで、詳細に解説します。
初心者の方から、コードの可読性を高めたい中級者の方まで、幅広く役立つ内容となっています。
continue文の基本概念と役割
C++のcontinue文は、ループ(for、while、do-while)の本体において、それ以降の処理をスキップして次の反復(イテレーション)の開始位置にジャンプさせるための制御構文です。
通常、ループ内の処理は上から下へと順番に実行されますが、特定の条件に合致した場合に「今回の処理はここまでにして、次の回に進みたい」というケースが発生します。
このような場面でcontinue文を使用することで、不要な処理を回避し、コードの構造をシンプルに保つことができます。
continue文の基本的な書式
continue文は、主にif文などの条件分岐と組み合わせて使用されます。
基本的な構造は以下の通りです。
for (初期化式; 条件式; 更新式) {
// 処理A
if (スキップしたい条件) {
continue; // 処理Bをスキップして更新式へジャンプ
}
// 処理B
}
この流れにおいて、条件に合致してcontinueが実行されると、「処理B」は実行されずに、forループの「更新式(i++など)」へと制御が移ります。
forループにおけるcontinue文の使い方
forループでcontinue文を使用する場合、最も注意すべき点は、continueが実行された直後に「更新式」が評価されるという点です。
これにより、無限ループに陥るリスクを抑えつつ、特定の要素を対象外にする処理が容易に記述できます。
具体的なプログラム例:奇数のみを表示する
以下のプログラムは、0から9までの数値のうち、偶数をスキップして奇数のみを表示する例です。
#include <iostream>
int main() {
std::cout << "0から9までの奇数を表示します:" << std::endl;
for (int i = 0; i < 10; ++i) {
// iが偶数の場合、以下の処理をスキップ
if (i % 2 == 0) {
continue;
}
// continueが実行されると、この行には到達しない
std::cout << i << " ";
}
std::cout << std::endl << "処理が完了しました。" << std::endl;
return 0;
}
0から9までの奇数を表示します:
1 3 5 7 9
処理が完了しました。
このプログラムでは、i % 2 == 0(偶数であること)が真になった瞬間にcontinue文が実行されます。
その結果、std::coutによる出力がスキップされ、カウンタ変数であるiのインクリメントへと処理が移ります。
whileおよびdo-whileループにおける注意点
whileループやdo-whileループでcontinue文を使用する際には、「無限ループ」の発生に細心の注意を払う必要があります。
forループとは異なり、更新式がループ構造の一部として組み込まれていないため、変数の更新処理を記述する位置によっては、更新が行われずに同じ条件でループし続けてしまうからです。
誤った実装例(無限ループ)
以下のコードは、continue文によって更新処理がスキップされてしまう典型的な失敗例です。
#include <iostream>
int main() {
int i = 0;
while (i < 5) {
if (i == 2) {
continue; // ここでジャンプすると「i++」が実行されない
}
std::cout << i << std::endl;
i++;
}
return 0;
}
この例では、i == 2になった時点でcontinueが実行されます。
しかし、i++はその後に記述されているため、iの値は2のまま固定され、無限にwhileの先頭に戻り続けることになります。
正しい実装例
whileループで安全にcontinueを使用するには、continueよりも前に更新処理を行うか、以下のように構造を工夫します。
#include <iostream>
int main() {
int i = 0;
while (i < 5) {
// 先にインクリメントを行うか、ifの前に更新ロジックを配置する
if (i == 2) {
i++; // スキップする前に手動で更新
continue;
}
std::cout << "Value: " << i << std::endl;
i++;
}
return 0;
}
Value: 0
Value: 1
Value: 3
Value: 4
このように、whileループでは「ループ変数の更新が確実に行われるか」を常に意識する必要があります。
continue文とbreak文の違い
ループ制御において、continue文と並んで頻用されるのがbreak文です。
これら二つは「ループの通常の流れを変える」という点では共通していますが、その効果は全く異なります。
| 機能 | continue文 | break文 |
|---|---|---|
| 動作の効果 | 現在の反復の残り処理をスキップし、次の回へ進む | ループ自体を即座に終了させる |
| ループの継続 | 条件が許す限り継続する | その時点で完全に終了する |
| 主な用途 | 特定の条件下での処理除外(フィルタリング) | 検索完了時や異常終了時の脱出 |
比較プログラム例
同じ条件でcontinueとbreakがどのように挙動を変えるかを確認してみましょう。
#include <iostream>
int main() {
std::cout << "--- continueの挙動 ---" << std::endl;
for (int i = 1; i <= 5; ++i) {
if (i == 3) continue;
std::cout << i << " ";
}
std::cout << "\n--- breakの挙動 ---" << std::endl;
for (int i = 1; i <= 5; ++i) {
if (i == 3) break;
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
--- continueの挙動 ---
1 2 4 5
--- breakの挙動 ---
1 2
continueは「3」だけを飛ばして最後まで実行していますが、breakは「3」に到達した時点でループそのものを放棄しています。
この違いを正しく理解し、目的に応じて使い分けることが重要です。
実践的なテクニック:ガード節によるネストの解消
continue文の最も有効な活用方法の一つに、「ガード節(Guard Clause)」としての利用があります。
これは、処理の対象外となる条件をループの先頭でチェックし、continueで弾いてしまう手法です。
これにより、メインの処理を深いif文のネストの中に書かずに済み、コードの可読性が飛躍的に向上します。
ネストが深いコード(読みにくい例)
for (int i = 0; i < data.size(); ++i) {
if (data[i] != nullptr) {
if (data[i]->isActive()) {
if (data[i]->hasPermission()) {
// ここにメインの複雑な処理が書かれる
process(data[i]);
}
}
}
}
continueを活用したコード(読みやすい例)
for (int i = 0; i < data.size(); ++i) {
// 処理対象外を先にはじく
if (data[i] == nullptr) continue;
if (!data[i]->isActive()) continue;
if (!data[i]->hasPermission()) continue;
// メインの処理をインデントを下げずに記述できる
process(data[i]);
}
このように、continue文を適切に使うことで、「どのような条件下で処理が行われるか」よりも「どのような条件ならスキップされるか」を明確に提示できるようになり、ロジックの見通しが良くなります。
多重ループにおけるcontinueの挙動
C++において、continue文は「それが記述されている最も内側のループ」に対してのみ作用します。
二重、三重のループを使っている場合、外側のループまでスキップされるわけではない点に注意が必要です。
二重ループでの動作確認
#include <iostream>
int main() {
for (int i = 1; i <= 3; ++i) {
for (int j = 1; j <= 3; ++j) {
if (i == 2 && j == 2) {
// i=2, j=2のときのみ内側のループの残りをスキップ
continue;
}
std::cout << "(" << i << "," << j << ") ";
}
std::cout << std::endl;
}
return 0;
}
(1,1) (1,2) (1,3)
(2,1) (2,3)
(3,1) (3,2) (3,3)
実行結果を見ると、(2,2)の出力だけがスキップされています。
しかし、外側のループ変数であるiはそのまま継続されており、(2,3)の処理は通常通り行われています。
もし内側から外側のループを一気に制御したい場合は、フラグ変数を利用するか、関数の設計を見直してreturnを使用するなどの工夫が必要になります。
continue文を使用する際のベストプラクティス
continue文は強力なツールですが、乱用すると逆にコードのフローを追いかけにくくする原因にもなります。
以下のポイントを意識して使用しましょう。
1. 条件式を単純に保つ
continueを呼び出すためのif文が複雑すぎると、なぜスキップされたのかを理解するのに時間がかかります。
条件が複雑になる場合は、あらかじめ論理変数を定義するか、条件判定自体を別の関数に切り出すことを検討してください。
2. ループの先頭付近で使用する
continueは「ガード節」として機能させるときに最大の効果を発揮します。
ループの処理の最後の方でcontinueを使用するのは、論理的にあまり意味がないことが多く、混乱を招くだけです。
基本的には、「処理の適格性を確認するフェーズ」としてループの冒頭に配置するのが定石です。
3. 巨大なループでの利用に限定しない
数行程度の短いループであれば、if-else文で事足りることも多いです。
continue文が真価を発揮するのは、ループ内の処理が長く、インデントを深くしたくない場面であることを覚えておきましょう。
まとめ
C++のcontinue文は、ループ処理の制御を柔軟に行うための重要なキーワードです。
特定の反復をスキップし、効率的に次の処理へと移行させることで、コードのネストを浅く保ち、可読性を向上させるメリットがあります。
本記事で解説したポイントを振り返ります。
- continue文は現在のループの残り処理をスキップし、次のイテレーションを開始する。
- forループではcontinue後に更新式が実行されるが、whileループでは無限ループにならないよう更新位置に注意が必要。
- break文との最大の違いは「ループを抜けるか、次の回へ進むか」という点にある。
- ガード節として活用することで、複雑な条件分岐のネストを解消し、メンテナンス性の高いコードを書くことができる。
ループ制御をマスターすることは、バグの少ない洗練されたプログラムを書くための第一歩です。
continue文を正しく使いこなし、スマートなC++プログラミングを実践していきましょう。






