Javaプログラマーだった僕が不思議に思った、C++変数の初期化について解説します。
変数を初期化しないのに動く?
C++のプログラムを修正していると、何も値を代入していない変数を平然と使っているソースコードを見かけます。
こんな感じです。
int _tmain(int argc, _TCHAR* argv[])
{
Foge foge;
std::cout << foge.int_a;
}
この変数fogeには、値が何も代入されていません。
インスタンスのない変数のメンバであるint_aを参照しています。
Javaだったらこれはコンパイルエラーになりますが、C++でコンパイルも通りますし普通に動いちゃうんです。
不思議ですよね。
変数fogeには何が入っているのでしょうか…?
暗黙的に呼び出されるデフォルトコンストラクタ
実は、C++では値の代入を省略すると、デフォルトコンストラクタが暗黙的に呼び出されるのです。
- 引数の指定がないコンストラクタ
- コンストラクタが1つも定義されていなければ自動生成される
暗黙的に、引数なしのコンストラクタが呼ばれるという事なので、下記の2つのソースコードはイコールになります。
Foge foge;
Foge foge = Foge();
変数の中身はかっらぽかと思っていましたが、暗黙的にインスタンスが代入されていたのでコンパイルエラーにもならずに、正常に動作していたんですね。
暗黙的代入を利用する際の注意点
暗黙的代入を利用する場合、いくつか注意点があります。
下記のようなケースはエラーになってしまうので注意です。
基本型は暗黙的代入の対象外
下記のコードはエラーになります。
int a;
std::cout << a;
基本型は暗黙的に初期化されません。
引数なしコンストラクタがないクラスは暗黙的代入の対象外
こちらのケースもエラーになります。
class Foge {
public:
int int_a;
Foge(int param){
int_a = param;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Foge foge;
std::cout << foge.int_a;
return 0;
}
このクラスはデフォルトコンストラクタがありません。
コンストラクタが1つも実装されていなければ、デフォルトコンストラクタが自動生成されるのですが、1つでも実装されていれば生成されません。
このFogeクラスは、Foge(int param)の引数ありコンストラクタしか存在しないのです。
デフォルトコンストラクタが存在しないので、デフォルトコンストラクタを呼び出す暗黙的代入が機能しないということです。
下記のソースコードは正常に動きます。
class Foge {
public:
int int_a;
};
int _tmain(int argc, _TCHAR* argv[])
{
Foge foge;
foge.int_a = 1;
std::cout << foge.int_a;
return 0;
}
このコードでは、Fogeクラスにコンストラクタが何も実装されていませんので自動的にデフォルトコンストラクタ生成されます。
デフォルトコンストラクタがあれば、暗黙的代入が作動するので問題なく動くという事です。
まとめ
C++で何も値を代入していない変数は、一見カラのように見えますが、暗黙的にデフォルトコンストラクタで生成されたオブジェクトが代入されています。
ただし、暗黙的に値が代入されるには条件があり、一概にC++で初期化不要と言えるわけではありません。
ソースコードの可読性や、後から引数ありコンストラクタを定義したら動作しなくなるリスクを考えると、暗黙的代入に頼らず変数は初期化する癖をつけておいたほうが良さそうですね。
この記事が少しでも参考になれば幸いです。
最後までお読みいただきありがとうございました。