いいえ、のコンストラクタはobject
、呼び出されobject
て返される関数とは大きく異なりobject
ます。コンストラクタには名前がありませんが、それは主に技術的なことです。さらに重要な違いは、コンストラクターには戻り値の型がないことと、コンストラクターを直接呼び出すことができないことです。
コンストラクターはメモリブロックが与えられ、そのメモリをインプレースで操作するため、何も返しません。「コンストラクタ」という名前を一瞬忘れて、代わりにイニシャライザと考えると役立つ場合があります。コンストラクターの目的は、「薄い空気から」オブジェクトを構築することではありません。その目的は、オブジェクトをメモリ内の必要な場所に正確に初期化することです。
コンストラクターがオブジェクトを返す場合、その返されたオブジェクト(戻り値)はどこかに(おそらくスタック上に)存在する必要があり、そこで何らかの方法で初期化する必要があります。ここでループに遭遇しています。
これは、コンストラクターを直接呼び出すことはできないという事実と関連しています。クラスがobject
あり、object()
どこかで式を使用する場合、「のコンストラクターを呼び出す」というセマンティクスはありませんobject
。object
「タイプの一時オブジェクトを作成する」というセマンティクスがあります。コンパイラーはこれを、一時変数が(おそらく/通常はスタック上に)存在する場所を割り当て、その場所でオブジェクトを構築(=初期化)するためにコンストラクターを呼び出すことに変換します。
同じ原理がを使用するときに適用されますnew object()
。これは、次の2つのことを行う新しい式です。
- オブジェクトに未加工のメモリを割り当てるに
operator new
は、割り当て関数(を返すvoid*
)を呼び出します。
- このrawメモリにコンストラクター呼び出しを発行して、そのrawメモリの一部にオブジェクトを構築(=初期化)します。
のコンストラクタを次のobject
ような関数と考えます。
static object object();
間違っている。どちらかといえば、コンストラクタの動作はこれに近いです:
static void object(object &place_to_work_in);
ただし、直接呼び出すことはできません。これは常に、異なる言語構造によって指定された場合にのみ呼び出されます。新しい配置(「ここでコンストラクタを呼び出す」トリックとも呼ばれます)でもnew (&place_for_object) object()
、コンストラクタを直接呼び出しません。これは、placement-new形式の呼び出しに変換され、operator new
その引数が返され、その後にコンストラクタが呼び出されます(他のnew-expressionと同様)。