宣言 (declaration) と定義 (definition) の違い

名前 (識別子) の型をコンパイラに伝えるのが宣言で、その名前が参照している実体 (メモリ) を確保するのが定義です。

宣言とその定義
分類 宣言 定義
変数
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は無視され、定義となります。

定義 (definition)

次のように定義するとき、

int x = 1;

これを構成する要素は、それぞれ

  • int … 基本型 (base type)
  • x … 宣言子 (declarator)
  • = 1 … 初期化子 (initializer)

の意味を持ちます。

初期化子 (Initializer) / 初期設定子

初期化子の形式
   
int x = 1; 等号と、それに続く式
MyStruct s(1, 2); 丸かっこ内の式 (引数付きコンストラクタ)
MyStruct s{1, 2}; 波かっこで囲まれた、初期化子リスト (initializer list)
(省略可能)
MyStruct s{};
初期化子 | MSDN

ゼロ初期化 (Zero initialization)

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

既定値初期化 (Default initialization)

クラスや構造体は、初期化子の省略またはnew演算子によって既定のコンストラクタが呼び出され、それによって既定値に初期化されます。

MyClass  myClass1;               // 初期化子の省略
MyClass* myClass2 = new MyClass; // new演算子

参考

参考書

Microsoft Learnから検索