2011-05-18 17 views
7

Tengo una clase que no es copiable (un hilo, por lo que no hay semántica de copia que tenga sentido), y quiero tener una 'matriz' amplia de estos, construida de manera idéntica con un constructor no predeterminado Tenga en cuenta que la matriz es de tamaño fijo.Construyendo "matriz" de objetos no procesables

Solo puedo usar el constructor predeterminado con las matrices C++, a menos que inicialice cada una de forma independiente.

Thread myArray[128]; // uses default constructor - wrong 

Puedo hacer una lista de constructores de objetos y parámetros de forma explícita, pero eso es prolijo y feo

Thread myArray[128] = { Thread(params,...), Thread(params,...), ... x 128 ; // ugly 

Parece que no puedo usar vectores stl porque el objeto no es copiable - caso de que el vector nunca cambia de tamaño ¡Supongo que el constructor realmente copia!

std::vector<Thread> myVector(128, Thread(params,...));// won't compile 

La forma en que he pesar de hacer esto es con una matriz de punteros inteligentes y un bucle de inicialización, pero tal vez me falta algo:

¿Hay alguna otra manera - tal vez con los envases de impulso ¿o un tipo de contenedor diferente?

+3

El uso de un puntero inteligente parece lo más sensato. No creo que haya una mejor manera. –

+1

Si están "construidos de forma idéntica", ¿no puedes agregar un constructor predeterminado que haga eso? De lo contrario, vaya con @ Space_C0wb0y. –

+0

La biblioteca Qt es una biblioteca bastante famosa, y manejan matrices de objetos no copiables (los widgets de GUI, totalmente no copiables) con punteros. Así que supongo que los indicadores inteligentes son el camino a seguir. – Fezvez

Respuesta

3

Un vector de punteros inteligentes, con cada instancia dinámicamente asignada , es definitivamente la forma más sencilla. De lo contrario (y me gustaría solo hacer esto si es absolutamente necesario), puede más o menos emular lo que std::vector hace internamente. Algo a lo largo de las líneas de :

union 
{ 
    double just_to_ensure_alignment; 
    unsigned char data[ sizeof(Thread) * elementCount ]; 
} array; 

// construct... 
for (int i = 0; i != elementCount; ++ i) 
    new (data + i * sizeof(Thread)) Thread(params,...); 

// access... 
Thread& getAt(int i) 
{ 
    return reinterpret_cast<Thread*>(data + i * sizeof(Thread)); 
} 

(me había hecho envolver esto en una clase, aunque sólo sea para poder utilizar operator[] en lugar de getAt.)

+0

Gracias. Terminé usando una matriz de boost :: shared_ptr – Roddy

6

Esto puede parecer totalmente loco (y probablemente lo sea), pero ...

struct ThreadInitValues{ 
    // your actual params 
    int i; 
    float f; 
}; 

struct Thread{ 
    Thread(int i = _init.i, float f = _init.f) 
     : _i(i) 
     , _f(f) 
    {} 

    static ThreadInitValues _init; 

private: 
    // uncopyable 
    Thread(Thread const&); 
    Thread& operator=(Thread const& other); 

    // your actual member 
    int _i; 
    float _f; 
}; 

ThreadInitValues Thread::_init; 

int main(){ 
    Thread::_init.i = 5; 
    Thread::_init.f = 3.14f; 
    Thread arr[128]; 
} 

Tal vez esto funciona para usted. :) Por supuesto, ahora necesita observar si la matriz se inicializó en código multiproceso en sí ...

+5

+1 por loco. Pero creo que la variedad de punteros inteligentes es más idiomática y más fácil de leer. – Roddy

1

Para los nuevos compiladores de apoyo a la I-valor las referencias, siendo copiables no son necesarias para los elementos vectoriales AFAIK. Para usarlo sin copiar 128, se debe usar push_back (creando un nuevo objeto cada vez), porque crear varios objetos a partir de uno solo es a copiar :).

Si esta forma no está disponible, pruebe boost::ptr_vector o std :: vector of boost :: shared_ptr.

+0

Atención: MSVC intenta falsificar el acceso al copiador en copia elisión aunque debe acceder al movimiento ctor – Xeo

+0

Hmm. Pero, ¿el constructor 'myVector (128, Thread (params, ...))' no tendrá que copiar? Después de todo, solo estoy pasando un objeto y quiero crear 128 ... – Roddy

+0

He actualizado la respuesta, simplemente use push_back. – maxim1000

0

No soy un gran programador. Pero intentó esto

std::vector<YourObject *> temp_Vec; 
for(int i=0;i<128;++i) 
    temp_Vec.push_back(new YourObject(arguments)); 
+1

Punteros inteligentes serían mucho más seguros. boost :: scoped_ptr, por ejemplo. – Roddy

Cuestiones relacionadas