C++入門|ローカル変数とスコープ

変数の居場所がわかると、C++はぐっと読みやすくなる。ローカル変数とスコープを、修行場のルールのようにやさしく理解しよう。

C++を学んでいると、変数をどこで宣言するか、そしてその変数をどこまで使えるのかがとても大切になってきます。
この考え方が、ローカル変数スコープです。

ドラゴンボール風にたとえるなら、変数は修行場に入る戦士のようなものです。
戦士は、決められた修行エリアに入ってはじめて活動できます。反対に、そのエリアの外では活動できません。

C++では、この「どこで使えるか」のルールがとてもはっきりしています。
しかもC言語より柔軟で、必要になった場所で変数を宣言しやすくなっています。

C言語では、ローカル変数は関数の先頭でまとめて宣言するのが基本でした。
一方C++では、使いたい場所の近くで宣言できるのが大きな特徴です。

これは見た目の小さな違いに見えますが、実際にはかなり大きなメリットがあります。

  • 必要な場所で変数を作れる
  • 変数の役割がわかりやすい
  • 使う範囲を狭くできる
  • 間違って別の場所で使ってしまうミスを減らせる

つまりC++では、変数を必要な修行場だけに登場させるような感覚で書けるわけです。

ここでは、まずローカル変数を処理の途中で宣言する例を見て、そのあとでfor文の中で変数を宣言する書き方、さらにスコープの意味まで順番に見ていきましょう。

図:ローカル変数は必要な場所で登場できる

この図が示していること

この図では、C++ではローカル変数を関数の先頭だけでなく、必要になった場所で宣言できることを表しています。

変数 i は、main関数の最初から存在しているのではなく、宣言した位置で登場し、そこから先で使えるようになります。
つまり、変数はどこでも自由に使えるわけではなく、宣言された位置から有効になるということがわかります。

ローカル変数とは何か

ローカル変数とは、関数の中やブロックの中で宣言される変数のことです。
その変数は、宣言された場所を含む限られた範囲だけで使えます。

ドラゴンボール風にいえば、ローカル変数は特定の修行場に所属する戦士です。
天下一武道会の会場にいる戦士が、いきなり別の惑星の修行場で活動できないのと同じで、ローカル変数も決められた範囲の中でだけ働きます。

C++では、このローカル変数をとても柔軟に扱えます。
C言語よりも「必要な場面で必要なだけ登場させる」という書き方がしやすいのがポイントです。

C言語とC++で違うローカル変数の宣言位置

C言語では、ローカル変数は関数の先頭でまとめて宣言する書き方が基本でした。
そのため、処理を書いている途中で新しい変数を宣言すると、環境によってはエラーになることがありました。

一方、C++では違います。
処理の途中で変数を宣言しても問題ありません。

これはとても便利です。
なぜなら、変数を使う直前に宣言できるので、コードが読みやすくなるからです。

たとえば、修行を始めるメッセージを表示したあとで、回数を数えるための変数が必要になったとします。
C++なら、そのタイミングで変数を宣言できます。

処理の途中でローカル変数を宣言する

まずは、処理の途中でローカル変数を宣言している例を見てみましょう。

プロジェクト/ファイル名: Chap2_10/main.cpp

#include <iostream>

using namespace std;

int main(int argc, char** argv) {
    cout << "修行を開始します。" << endl;

    // 処理の途中で回数を表す変数を宣言
    int i;

    for (i = 0; i < 10; i++) {
        cout << "気の段階:" << i << " ";
    }

    cout << endl;

    for (i = 0; i < 3; i++) {
        cout << "呼吸を整えます。" << endl;
    }

    return 0;
}

実行結果

修行を開始します。
気の段階:0 気の段階:1 気の段階:2 気の段階:3 気の段階:4 気の段階:5 気の段階:6 気の段階:7 気の段階:8 気の段階:9
呼吸を整えます。
呼吸を整えます。
呼吸を整えます。

このプログラムのポイントは、メッセージを表示したあとに、

int i;

と書いているところです。

C++では、このように処理の途中で変数を宣言できるのが特徴です。

Chap2_10/main.cpp の流れを見てみよう

このプログラムは、次のような流れで動いています。

  1. まず、修行開始のメッセージを表示する
  2. そのあとで、繰り返し用の変数 i を宣言する
  3. 最初のfor文で、0から9までの値を順番に表示する
  4. 改行する
  5. 2つ目のfor文で、同じ変数 i を使って3回メッセージを表示する
  6. プログラムを終了する

ここで大事なのは、変数 i が関数の先頭ではなく、必要になった場所で宣言されていることです。

C++では、この書き方が自然にできます。
そのため、変数の役割が見つけやすくなります。

たとえば、いちばん上に大量の変数が並んでいると、どの変数がどこで使われるのか見つけにくくなります。
でも、使う少し前で宣言してあれば、コードを読む人にとってとても親切です。

ローカル変数は宣言された場所から使える

ローカル変数は、宣言した瞬間から使えるようになります。
逆にいうと、宣言する前には使えません。

今回のプログラムでは、i は

int i;

と書かれた位置から下で使えるようになります。

そのため、次の2つのfor文の両方で i を使えています。

for (i = 0; i < 10; i++)

for (i = 0; i < 3; i++)

これは、i がmain関数の中で宣言されていて、その後ろの処理全体で有効だからです。

ドラゴンボール風にいうなら、変数 i はmain修行場の途中で会場入りした戦士です。
その時点から、同じ会場の中では活動できます。

スコープとは何か

ここで登場する重要な言葉が、スコープです。

スコープとは、変数や関数名などが有効な範囲のことです。

変数には、どこでも使える自由があるわけではありません。
決められた範囲の中でだけ使えます。
この「ここからここまで使える」という範囲がスコープです。

用語意味
ローカル変数関数やブロックの中で宣言する変数
スコープその名前を使える範囲
ブロック{ } で囲まれた範囲

ドラゴンボール風にたとえるなら、スコープは修行場の担当エリアです。
たとえば、ある戦士が重力室の担当なら、重力室の中では活動できますが、別の修行エリアに勝手には出られません。

C++では、このスコープを意識することがとても大切です。

図:スコープは変数が活動できる範囲

この図が示していること

この図では、変数 i が宣言された場所から有効になり、その後ろの決められた範囲の中だけで使えることを示しています。

つまり、スコープとは単なる場所の名前ではなく、その変数が活動できる範囲そのものです。
変数の役割と寿命を整理して考えるために、スコープの理解はとても重要です。

for文の中で変数を宣言する

C++ではさらに便利な書き方があります。
それが、for文の中で変数を宣言する書き方です。

次のプログラムを見てみましょう。

プロジェクト/ファイル名: Chap2_11/main.cpp

#include <iostream>

using namespace std;

int main(int argc, char** argv) {
    cout << "修行を開始します。" << endl;

    // 最初のfor文の中で変数を宣言
    for (int i = 0; i < 10; i++) {
        cout << "修行番号:" << i << " ";
    }

    cout << endl;

    // 2つ目のfor文の中で再び変数を宣言
    for (int i = 0; i < 3; i++) {
        cout << "気を落ち着けます。" << endl;
    }

    return 0;
}

実行結果

修行を開始します。
修行番号:0 修行番号:1 修行番号:2 修行番号:3 修行番号:4 修行番号:5 修行番号:6 修行番号:7 修行番号:8 修行番号:9
気を落ち着けます。
気を落ち着けます。
気を落ち着けます。

このプログラムでは、変数 i をfor文の中で宣言しています。

for (int i = 0; i < 10; i++)

この書き方では、i のスコープはそのfor文の中だけになります。

つまり、最初のfor文で使う i と、2つ目のfor文で使う i は、同じ名前に見えても別のローカル変数です。

for文の中で宣言するメリット

for文の中で変数を宣言するメリットはとても大きいです。

1. 変数の役割がはっきりする

for文のためだけに使う変数なら、そのfor文の中で宣言したほうがわかりやすいです。
コードを読んだときに、「この i はこの繰り返し専用なんだな」とすぐにわかります。

2. 変数の使いすぎを防げる

変数を広い範囲で使えるようにしてしまうと、意図しない場所で使ってしまうことがあります。
でも、for文の中に閉じ込めておけば、外からは使えません。

3. 同じ名前を別のループで使いやすい

最初のfor文の i と、次のfor文の i は別物として扱えます。
これは、ループごとに担当戦士を入れ替えるようなイメージです。

書き方使える範囲特徴
int i; を先に宣言宣言位置からブロック末尾まで複数の場所で共有しやすい
for (int i = ... )そのfor文の中だけ繰り返し専用として使いやすい

Chap2_10 と Chap2_11 の違い

この2つのプログラムは、動きとしてはよく似ています。
でも、変数 i のスコープは違います。

Chap2_10 の場合

int i;

をmain関数の途中で宣言しているので、
その後ろにある2つのfor文の両方で同じ i を使っています。

Chap2_11 の場合

for (int i = 0; i < 10; i++)

のように書いているので、
最初のfor文の i は最初のfor文の中だけ、
2つ目のfor文の i は2つ目のfor文の中だけ有効です。

これをドラゴンボール風にたとえると、Chap2_10は1人の戦士が2つの修行メニューを続けて担当している形です。
Chap2_11は、最初の修行コース専用の戦士と、次の修行コース専用の戦士がそれぞれ別にいる形です。

スコープが狭いほど安全でわかりやすい

一般的に、変数のスコープは必要以上に広くしないほうが読みやすく、安全です。

なぜなら、使える範囲が広いと、

  • どこで値が変わったのか追いにくい
  • 似た役割の変数が混ざりやすい
  • 思わぬ場所で使ってしまうことがある

といった問題が起こりやすくなるからです。

そのためC++では、変数はできるだけ使う場所の近くで宣言し、スコープを狭くするのがよい書き方です。

これはとても大事な考え方です。

たとえば、for文のためだけに必要な変数を、関数の最初にわざわざ宣言しておく必要はあまりありません。
for文の中で宣言してしまったほうが、コードの意図がはっきりします。

ブロックの中でだけ使えるという感覚を持とう

スコープを理解するときは、{ } の中がひとつのエリアになると考えるとわかりやすいです。

for文やif文、while文などでは、{ } で囲まれた中がひとまとまりのブロックになります。
その中で宣言した変数は、原則としてそのブロックの外では使えません。

たとえば、for文の中で宣言した i は、for文が終わったあとには使えません。
つまり、その変数は修行場を出たら役目を終える戦士のようなものです。

この感覚を持てると、ローカル変数の意味がかなりつかみやすくなります。

変数をどこで宣言するかの考え方

C++でローカル変数を宣言するときは、次のように考えるとわかりやすいです。

関数全体で使うなら、関数の中で早めに宣言する

同じ変数を複数の処理で使うなら、関数の中の少し広い範囲で使えるように宣言します。

ある処理専用なら、その処理の近くで宣言する

for文のカウンタのように限定された用途なら、for文の中で宣言するのが自然です。

使う範囲はなるべく狭くする

これはC++らしいきれいな書き方をするうえでとても大切です。

場面おすすめの宣言場所
関数の後半で何度も使う使い始める少し前
for文だけで使うfor文の初期化部分
一時的な計算だけで使うその計算の近く

C言語との違いとして覚えておきたいこと

今回のテーマで、特に覚えておきたいC++とC言語の違いは次の2つです。

項目C言語C++
変数宣言の位置関数の先頭でまとめるのが基本処理の途中でも宣言できる
for文での宣言環境によっては注意が必要自然に使える
コードの書き方まとめて宣言することが多い必要な場所で宣言しやすい

C++では、変数を必要な場所で宣言できるので、コードを整理しやすくなります。
また、for文の中でカウンタ変数を宣言する書き方もとてもよく使われます。

なお、近年のC言語ではC++に近い書き方が使える場合もあります。
ただし、コンパイラや設定によって仕様の違いが出ることがあるため、C言語として考える場合は注意が必要です。

ローカル変数とスコープを意識するとコードが読みやすくなる

ローカル変数とスコープを意識できるようになると、コードの見通しがかなりよくなります。

変数はただ宣言すればよいわけではなく、

  • どこで登場するか
  • どこまで使えるか
  • 本当にその範囲で使う必要があるか

を考えることが大切です。

ドラゴンボール風にいえば、戦士を必要な修行場にだけ配置する感覚です。
あちこちに同じ戦士を出しっぱなしにするより、必要な場所で必要なときだけ登場させたほうが、全体の動きがはっきりします。

図:for文の中で宣言した変数はそのループだけで有効

この図が示していること

この図では、for文の中で宣言した変数 i が、そのfor文の中でだけ有効であることを示しています。

左のループの i と右のループの i は、同じ名前でも別々のローカル変数です。
そのため、ループごとに役割を分けやすく、スコープを狭く保つことでコードが安全で読みやすくなることがわかります。

C++らしい書き方として覚えておきたいポイント

最後に、今回のテーマで特に大事なポイントを整理しておきましょう。

ローカル変数は必要な場所で宣言できる

C++では、関数の途中でも変数を宣言できます。
これはC++の大きな特徴のひとつです。

スコープは変数が使える範囲

変数はどこでも使えるわけではありません。
宣言された位置とブロックの範囲に応じて、使える場所が決まります。

for文の中で宣言するとスコープを狭くできる

for文専用の変数なら、for文の中で宣言するのが便利です。
コードの意味が伝わりやすく、余計なミスも防ぎやすくなります。

変数はできるだけ狭い範囲で使う

これはとても大切な考え方です。
必要以上に広いスコープを持たせないことで、読みやすく整理されたコードになります。

ローカル変数とスコープがわかるようになると、C++のコードはずっと見通しがよくなります。
変数をただ置くのではなく、どこで登場して、どこまで活動できるかを意識して書けるようになると、C++らしいきれいなプログラムにぐっと近づいていきます。