1

Squareコンストラクターで呼び出されたオブジェクトがあるとしましょう。コンストラクターSquare(int rx, int ry)で異なる引数を使用して、正方形の動的配列を作成したいとします。

Square *squares = new Square[10];  
for (int i = 0; i < 10; i++)
{
     squares[i] = new Square(i, i);
}

ただし、これは失敗し、適切なデフォルト コンストラクターが利用できないと表示されます。では、空または NULL 配列を作成し、後で構築するにはどうすればよいでしょうか。

編集:これは、コード内の他の理由により、ここで説明するのが難しい配列でなければなりません。

4

9 に答える 9

7

を使用しvectorます。Squareコピー可能である限り、この問題はありません。

vector<Square> squares;
for (int i = 0; i < 10; i++)
{
     squares.push_back(Square(i, i));
}
于 2011-03-30T16:47:04.737 に答える
5

へのポインターの配列を作成できますSquare

Square **squares = new Square*[10];

for (int i = 0; i < 10; i++)
{
     squares[i] = new Square(i, i);
}

他の人が指摘しているように、std::vector代わりに使用することを検討することをお勧めします。

于 2011-03-30T16:45:41.240 に答える
1

std::vector動的に割り当てられた配列の代わりに a を使用することをお勧めします。std::vectors は操作がはるかに簡単で、メモリ リークもありません。

ただし、エラー メッセージが参照する欠落しているコンストラクターはSquareのコンストラクターです。Square引数を取らない コンストラクタを追加する必要があります。のいずれかを行います。

class Square {
    Square() { ... }
    // Square with dimensions of 0 is empty
    Square(int length=0, int width=0) { ... }
    ...
};

これらの両方をファイルに入れると、引数が指定されていないときにどのコンストラクターを呼び出すかを知ることができないため、エラーが発生することに注意してください

を使用する場合でも、おそらくデフォルトのコンストラクターが必要になるでしょうstd::vectorstd::vector「おそらく」オブジェクトを受け取る のコンストラクターに限定すると、回避できるためです。たとえば、次のようになります。

std::vector<Square> foo(10, Square(0, 0));
// reassign each element accordingly

これは、質問自体へのコメントとして既に追加しています。Herb Sutter が言うように、std::vectorarray と交換できるように設計されています

ベクトルが連続していることがなぜそれほど重要なのですか? これは、ベクトルが C 配列とレイアウト互換であることを保証する必要があるためです。したがって、C コードとデータを交換する必要がある場合でも、配列に代わる優れた型安全な代替手段としてベクトルを使用しない理由はありません。そのため、Vector は他の言語やほとんどのオペレーティング システム機能へのゲートウェイであり、そのリンガ フランカは由緒ある C 配列です。

ちなみに、構文は (Assuming vis a vector)&v[0]です。つまり、最初の要素のアドレスを取得し (これは参照であるため、 をstd::vector除くすべての sstd::vector<bool>で機能します)、ポインターを期待する任意の関数に渡すことができるポインターを取得します (もちろん、として「配列」の長さを取得しますv.size())。

于 2011-03-30T16:52:59.023 に答える
1

へのポインタの配列を作成する必要がありますSQuare

ただし、std::vector「クラシック」配列の代わりに を使用することもお勧めします。これは、Squareコピー可能な場合に適したソリューションです。

ただし、そうでない場合、またはポインターを使用することに決めた場合は、すべての削除の負担をコンパイラーstd::vectorshared_ptr任せることをお勧めします。

これは次のようになります。

#include <vector>
#include <boost/shared_ptr.hpp> //on some compilers, you can use #include <memory> instead

using std::vector;
using boost::shared_ptr; // or using std::shared_ptr

vector<shared_ptr<Square> > squares(10);

for (int i = 0; i < 10; i++)
{
     squares[i].reset(new Square(i, i));
}

さらに先に進むには、Boost Pointer Container ライブラリを参照してください。

于 2011-03-30T16:47:44.220 に答える
1

標準ライブラリ コンテナがこれを行う方法は、新しい配置を使用することです。のような標準ライブラリ コンテナを使用するのstd::vectorが、間違いなく最も簡単な方法です。そして、新しい配置は最も難しいです。Xeoが述べたように、個々のオブジェクトを割り当てて配列にポインターを保持することは、中間に位置します。

于 2011-03-30T16:48:52.600 に答える
1

vector該当するプログラムで使用します。本当に raw を使用する必要がある場合はnew、placement new を使用できます。

Square *squares = static_cast<Square*>(operator new(sizeof(*squares) * 10));
for (int i = 0; i < 10; i++) {
  new (static_cast<void*>(squares + i)) Square(i, i);
}

で削除しoperator delete(squares);ます。これらのオブジェクトのデストラクタを手動で呼び出す必要があることに注意してください。または、未加工のストレージ イテレータを使用してオブジェクトを作成することもできます

std::raw_storage_iterator<Square*, Square> rsi(squares);
for (int i = 0; i < 10; i++) {
  *rsi++ = Square(i, i);
}

もちろん、使用の最後にデストラクタを手動で呼び出す必要はありません。

于 2011-03-30T16:51:07.413 に答える
0

ポインターへのポインターを単純に使用する

Square **squares = new Square*[10];  

そして、それはうまくいくはずです。しかし、ベクトルのような STL コンテナーを使い始めると、本当にうまくいくと思います。

于 2011-03-30T16:49:06.743 に答える
0

を使用するstd::vectorか、それと同じ手法を使用します。グローバルな new 演算子を使用して「生の」ストレージ スペースを割り当て、placement new を使用してそのストレージにオブジェクトを作成します (そして、delete を使用する代わりに dtor を直接呼び出してオブジェクトを破棄します)。

于 2011-03-30T16:49:11.523 に答える
0
Square *squares = new Square[10];

この操作は、既定のコンストラクターを10回呼び出します。また、スニペットにエラーが発生するものはありません。だから、それを提供してください。クラスメンバーを初期化するsetterメソッドを書くだけです。

for (int i = 0; i < 10; i++)
{
     squares[i] = new Square(i, i);
}

ループでnew再度操作すると、以前に取得したメモリをリークしているだけですが、思ったとおりに動作します。for

delete[]に電話することも忘れないでくださいsquares

于 2011-03-30T16:51:54.403 に答える