web-dev-qa-db-ja.com

オブジェクトポインタの配列の作成C ++

多くのオブジェクトへのポインタを保持する配列を作成したいのですが、保持するオブジェクトの数が事前にわかりません。つまり、配列にメモリを動的に割り当てる必要があります。私は次のコードを考えました:

ants = new *Ant[num_ants];
for (i=1;i<num_ants+1;i++)
{
    ants[i-1] = new Ant();
}

ここで、antsAnt **ants;として定義され、Antはクラスです。

うまくいきますか?

11
SIMEL

うまくいきますか?

はい。

ただし、可能であれば、ベクトルを使用する必要があります。

#include <vector>

std::vector<Ant*> ants;
for (int i = 0; i < num_ants; ++i) {
    ants.Push_back(new Ant());
}

動的に割り当てられた配列を使用する必要がある場合は、次の構文を使用します。

typedef Ant* AntPtr;
AntPtr * ants = new AntPtr[num_ants];
for (int i = 0; i < num_ants; ++i) {
    ants[i] = new Ant();
}

しかし、すべてを忘れてください。手動のメモリ管理が必要なため、コードはまだ良いものではありません。これを修正するには、コードを次のように変更します。

std::vector<std::unique_ptr<Ant>> ants;
for (auto i = 0; i != num_ants; ++i) {
    ants.Push_back(std::make_unique<Ant>());
}

そして何よりも、これは単純に次のようになります。

std::vector<Ant> ants(num_ants);
22
StackedCrooked
std::vector<Ant> ants(num_ants);
ants.resize(new_num_ants);
4
Erik

本当にアイテムにpointersを保持する必要がありますか?値でオブジェクトを使用できる場合、ベクトルを使用するのがはるかに簡単な方法です:std::vector<Ant> ants(num_ants);。そうすれば、ループを作成する必要がなくなるだけでなく、生のポインタやその他のオブジェクト管理アイテムからのメモリリークを心配する必要もなくなります。

APIを満たすためにオブジェクトポインターが必要な場合でも、外部コンテナーにvectorを使用して、オブジェクトを手動で割り当てることができます。

struct CreateAnt
{
    Ant* operator()() const { return new Ant; }
};

std::vector<Ant*> ants(num_ants);  // Create vector with null pointers.
std::generate(ants.begin(), ants.end(), CreateAnt());
3
Mark B

はい、それは一般的な考えです。ただし、代替手段があります。ポインタの配列が必要ですか?クラスAntのオブジェクトの配列で十分な場合があります。配列を割り当てる必要があるだけです:

Ant *ants = new Ant[num_ants];

一般に、配列を使用するよりもstd::vectorを使用することをお勧めします。ベクトルは必要に応じて拡張でき、メモリ管理を処理します。

投稿したコードでは、antsの各要素をループで削除してから、配列自体delete [] antを削除する必要があります。 deletedelete []の違いに注意してください。

もう1つ、C++の配列インデックスは0ベースであるため、次の規則を使用して要素を反復処理します。

for (i=0; i<num_ants; i++)
{
    ants[i] = new Ant();
}

これにより、コードがはるかに読みやすくなります。

2
Dima
std::vector<Ant*> ants( num_ants );
for ( int i = 0; i != num_ants; ++ i ) {
    ants[i] = new Ant;
}

または、事前に何件あるかわからない場合:

std::vector<Ant*> ants;
while ( moreAntsNeeded() ) {
    ants.Push_back( new Ant );
}

一方、Antがエンティティタイプなのか値なのかを自問する必要があると思います。値の場合は、ポインタと動的割り当てをスキップすることをお勧めします。エンティティタイプの場合は、オブジェクトの有効期間と、いつ、どこで削除されるかを考慮する必要があります。

2
James Kanze