2011-05-04 34 views
8

Quiero crear una matriz que contenga punteros a muchos objetos, pero no sé de antemano la cantidad de objetos que mantendré, lo que significa que necesito asignar dinámicamente memoria para la matriz He pensado en el siguiente código:creando una matriz de punteros a objetos C++

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

donde ants se define como Ant **ants; y Ant es una clase.

¿Funcionará?

+3

Quizás quiso probarlo? –

+0

@Carl Norum; no puedo probarlo en este momento, ya que solo estoy empezando a escribir el código, y todavía me faltan muchas partes. – SIMEL

+2

Es posible que desee cambiar su ciclo para iterar de 0 a num_ants, y asignarlo a las hormigas [i]. No hay necesidad de compensar todo por 1. –

Respuesta

15

Will it work?

Sí.

Sin embargo, si es posible, se debe utilizar un vector:

#include <vector> 

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

Si tiene que utilizar una matriz asignada dinámicamente entonces yo preferiría esta sintaxis:

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

Pero se olvidan de todo eso. El código aún no es bueno ya que requiere una gestión manual de la memoria. Para solucionar esto se podía cambiar su código para:

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

Y lo mejor de todo sería simplemente esto:

std::vector<Ant> ants(num_ants); 
+0

¿Se puede asignar realmente el resultado de 'new' a una matriz? –

+0

@Mark B: Buena captura. Arreglado. – StackedCrooked

+0

Así que básicamente 'new Ant * [num_ants]' es una llamada falsa, ya que no llama al constructor en absoluto ¿no? Solo asigna la matriz de puntero. Es por eso que el 'nuevo' parece como si se llamara dos veces. – Ciantic

4
std::vector<Ant> ants(num_ants); 
ants.resize(new_num_ants); 
+4

Si el OP quiere usar punteros para Hormigas, la declaración sería: 'std :: vector ant_pointers (num_ants);' –

+0

También tendría que usar 'std :: generate' to' new' todos los elementos respectivos. –

+0

He votado porque el OP mencionó directamente que quería usar punteros, lo que como @ThomasMatthews mencionó, necesita una declaración diferente. Sin embargo, tu respuesta es buena para un caso diferente. – Purefan

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

O si usted no sabe cuántos de antemano:

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

Por otro lado, creo que hay que preguntarse si Ant es un tipo de entidad o un valor . Si se trata de un valor, probablemente quiera omitir los punteros y la asignación dinámica; si se trata de un tipo de entidad, deberá tener en cuenta la duración del objeto y cuándo y dónde se eliminará.

2

Sí, esa es la idea general. Sin embargo, hay alternativas. ¿Estás seguro de que necesitas una serie de indicadores? Una matriz de objetos de la clase Ant puede ser suficiente. El que sólo tiene que asignar la matriz:

Ant *ants = new Ant[num_ants]; 

En general, se debe preferir el uso std::vector a la utilización de una matriz. Un vector puede crecer según sea necesario y gestionará la gestión de memoria por usted.

En el código que has publicado, se tendría que eliminar cada elemento de ants en un bucle, y luego eliminar la matriz en sí, delete [] ant. Tenga en cuenta la diferencia entre delete y delete [].

Un punto más, ya que los índices de matriz en C++ son 0-base, la siguiente convención se usa para iterar sobre los elementos:

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

Esto hace que el código mucho más legible.

3

¿De verdad necesita mantener punteros en los artículos? Si puede usar objetos por valor, un enfoque mucho más simple es usar un vector: std::vector<Ant> ants(num_ants);. Entonces no solo no tiene que escribir bucles, sino que no tiene que preocuparse por las pérdidas de memoria de los punteros sin procesar y otros elementos de administración de objetos.

Si necesita que los punteros de los objetos digan satisfacer una API, puede usar vector para el contenedor externo y asignar los objetos manualmente.

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());