名前 (識別子) の型をコンパイラに伝えるのが宣言で、その名前が参照している実体 (メモリ) を確保するのが定義です。
分類 | 宣言 | 定義 |
---|---|---|
変数 | extern int x; |
int x; |
関数 | int Func(); |
int Func() { } |
クラス | class MyClass; |
class MyClass { }; |
名前の定義は1つでなければなりませんが、宣言はいくつあっても構いません。ただしすべての宣言は、参照している実体の型が一致している必要があります。
たいていの宣言は定義でもあり、宣言と同時に実体も定義しています。
int x1; // 変数の定義 int x2 = 1; // 初期化子を伴う、変数の定義 int* x3; // ポインタの定義
int Func() { return; } // 関数定義 class MyClass { int a, b; }; // クラス定義
template<class T> T Func() { } // template宣言 typedef Type1<int> Type2; // typedef宣言
enum MyEnum { a, b, c }; // 列挙型の定義 namespace MyNamespace { int a; } // 名前空間を用いた、変数の定義
また初期値を与える場合はすべて定義であり、
extern int x;
とすると宣言ですが、
extern int x = 1;
として初期値を与えるとexternは無視され、定義となります。
次のように定義するとき、
int x = 1;
これを構成する要素は、それぞれ
の意味を持ちます。
int x = 1; | 等号と、それに続く式 |
MyStruct s(1, 2); | 丸かっこ内の式 (引数付きコンストラクタ) |
MyStruct s{1, 2}; | 波かっこで囲まれた、初期化子リスト (initializer list) (省略可能) |
MyStruct s{}; |
struct MyStruct { int i; char c; }; int x; // 0 に初期化される (ファイル スコープ) int main() { static float f; // 0.000000000 に初期化される (静的な変数) double d{}; // 0.00000000000000000 に初期化される (初期化子リスト) int* ptr{}; // nullptr に初期化される (初期化子リスト) char s_array[3]{ 'a', 'b' }; // 値が指定されていない3番目の要素は、'\0' に初期化される int int_array[5] = { 8, 9, 10 }; // 値が指定されていない4番目と5番目の要素は、0 に初期化される MyStruct a_struct{}; // i = 0, c = '\0' }初期化の種類 - 初期化子 | MSDN
クラスや構造体は、初期化子の省略またはnew演算子によって既定のコンストラクタが呼び出され、それによって既定値に初期化されます。
MyClass myClass1; // 初期化子の省略 MyClass* myClass2 = new MyClass; // new演算子