25

また、要素にデフォルトのコンストラクターを必要としないように、独自の配列クラスを作成するにはどうすればよいですか?現在、スペースを割り当てるためにnew []を実行するときは、デフォルトのコンストラクターが必要です。

std::vectorはしません。

彼らはどのようにこの魔法をしますか?

4

4 に答える 4

32

std::vectorデフォルトのコンストラクターは使用しないため、必要ありません。要素を構築する必要があるたびに、コピー コンストラクターを使用してそれを行います。これは、既存のベクター要素またはメソッドのパラメーターを介してコピーするために自分で指定した要素のいずれかをコピーする必要があるためです (明示的または暗黙的に、デフォルトの引数で)

そのようなクラスは、まったく同じ方法で作成できます。配列に新しい要素を作成する必要があるたびに、コピーする要素をユーザーに提供するように要求します。この場合、元の要素の構築はユーザーの責任になります。

std::vectorあなたからのデフォルトのコンストラクタを「必要とする」ように見えるたびに、それは単に、いくつかのvectors メソッドのデフォルトの引数にどこかで依存したことを意味します。つまり、ベクトルではなく、要素をデフォルトで構築しようとしたのはあなたでした。ベクトル自体も、要素をデフォルトで構築しようとはしません。

メモリ割り当て中のデフォルトのコンストラクタ要件を回避するために、標準ライブラリは生の初期化されていないメモリ ブロックを割り当てすぐにその生のメモリ ブロックに新しい要素をコピー構築します (これはnew[]実行できません)。この機能はstd::allocatorクラスにカプセル化されています。コードでも使用できますstd::allocator。つまり、「魔法」もすぐに利用できます。

注:上記は、C++ 言語仕様の C++11 より前のバージョンに適用されます。C++11 は多くのことを変更しました。そして、これらの変更により、std::vector内部で既定のコンストラクターを使用できる状況が作成されます。

また、元の C++98 仕様でさえ、標準ライブラリ インターフェイスを実装するために、既定の引数の代わりに関数のオーバーロードを使用することを実装に許可していたことに注意してください。これは、デフォルトのコンストラクターを内部的に使用する有効な C++98 実装を正式に持つことができることを意味します。std::vector

于 2010-03-04T05:13:38.620 に答える
11

std::vectorデフォルトのコンストラクターを必要とする方法で使用する場合にのみ、要素にデフォルトのコンストラクターが必要です。Xしたがって、デフォルトの ctor がないため、このコード (削除された回答から盗まれた) はコンパイルされません。

#include <vector>

struct X
{
  X(int) {}
};

int main(void)
{
  std::vector<X> x(1); // vector of length 1, second argument defaults to X() !!
  return 0;
}

しかし、main代わりに次のように書くと:

int main(void)
{
  std::vector<X> x; // make empty vector
  x.push_back(X(1));
  return 0;
}

その後、正常に動作します。

于 2010-03-04T05:15:28.527 に答える
8

バイトのブロックを割り当ててから、プレースメントnewTを使用して、新しいアイテムがベクターの後ろにプッシュされたときに、コピーコンストラクター(もちろんデフォルトのコンストラクターではありません)を介して(パラメトリックタイプ)の新しいインスタンスを作成できます。これでは、「デフォルトで初期化されたN個のTのベクトル」を作成することはできません(std :: vectorで作成できます。そのため、この目的でデフォルトのコンストラクターをTに含める必要があります)が、開始するベクトルを作成することはできます空で、Tをプッシュすることができます。

于 2010-03-04T05:06:31.970 に答える