2010-01-20 11 views
6

favor considere lo siguiente:C contenedor STL ++ y la construcción en el lugar

class CMyClass 
{ 
public: 
    CMyClass() 
    { 
    printf("Constructor\n"); 
    } 
    CMyClass(const CMyClass&) 
    { 
    printf("Copy constructor\n"); 
    } 
}; 

int main() 
{ 
    std::list<CMyClass> listMyClass; 

    listMyClass.resize(1); 

    return 0; 
} 

Se produce el siguiente resultado:

Constructor

constructor de copia

Ahora mi La pregunta es: ¿Cómo evito el constructor de copias? O para decirlo de otra manera: ¿cómo puedo crear objetos dentro de un contenedor STL sin la operación de copia innecesaria? ¿Hay alguna forma de hacer una construcción "in situ" utilizando el constructor predeterminado?


Actualizar - respuestas hasta el momento:

  1. No se puede hacer
  2. utilizan punteros o punteros inteligentes lugar.

Los punteros inteligentes son un exceso para mi aplicación. Pero realmente me pregunto por qué no se puede hacer esto. Parece algo tan obvio como querer hacer. ¿Alguna otra idea? Incluso voy a aceptar un corte desagradable si funciona ...


Solución

Creo que acabo de encontrar una solución para mi problema de todos los comentarios y respuestas planteadas aquí. La solución es construir un objeto vacío y guardarlo con el único propósito de usarlo más adelante para hacer copias limpias de. Luego puede usar uno de los métodos que toman una referencia (como push_back o insert). Esto todavía llama al constructor de copia para cada nuevo objeto insertado, pero al menos no lo es tanto el constructor por defecto y copiar constructor:

int main() 
{ 
    CMyClass Empty; 

    std::list<CMyClass> listMyClass; 

    for (int c=0; c<10; ++c) 
    { 
    listMyClass.push_back(Empty); 
    } 

    return 0; 
} 
+0

Podría parecer una algo obvio, pero desde un punto de vista funcional, no importa y varios algoritmos (ordenar, eliminar, ...) también usan copia, así que prepárate para ser copiado;) (Ver también http: //www.devx .com/tips/Tip/13606) – stefaanv

+0

¿Algo obvio que hacer? ¿Porqué es eso? ¿Por qué está copiando un problema? – jalf

+0

¿Obvio? Si llama a 'mylist.resize (10)', ¿cómo esperaría terminar con diez objetos distintos si no son copias? – visitor

Respuesta

8

Por diseño, todos los contenedores de C++ Standard Library almacenan copias. Por lo tanto, la llamada al constructor de copias no se puede evitar si desea almacenar valores en el contenedor; la única salida es almacenar punteros en su lugar. Si desea mitigar la sobrecarga de la copia, investigue el uso del recuento de referencias.

1

uso de punteros

std::list<CMyClass*> listMyClass; 
+2

aún mejor: use un puntero inteligente, creando/destruyendo automáticamente el objeto en cuestión – user231967

+2

Simplemente no es un auto_ptr. Eso causará que sucedan cosas malas. –

1

Lo sentimos, actualmente no con std :: lista y contenedores similares. (Sin embargo, usted puede escribir su propio contenedor ligeramente diferente si realmente necesita esto, y aún así seguir el resto de la interfaz STL.)

Usted no tiene que utilizar el ctor defecto, sin embargo:

std::list<CMyClass> listMyClass; 
listMyClass.resize(1, obj_to_copy_from); 

Tales como:

std::list<CMyClass> listMyClass; 
listMyClass.resize(1, CMyClass(use, specific, ctor)); 

cambio de tamaño se parece a:

void list<T>::resize(size_type new_size, T copy_from = T()); 

que crea un nuevo objeto (u cantar el ctor predeterminado) de forma predeterminada.

0

uso de un puntero o puntero inteligente (boost :: shared_ptr y no auto_ptr)

1

sería útil si el vector de inicialización permitió nuevos elementos con el constructor por defecto de cambio de tamaño debido a la actuación, pero esto no es compatible. Si realmente lo necesita, implemente un contenedor personalizado; no hay otra forma.

0

se puede hacer en c11, para las versiones anteriores, vesry sencilla se puede mejorar

vector

myclas: public vector<A> 
{ 
    push_back(Aconstructor_parameters) 
    { 
     new(_Mylast++) A(Aconstructor_parameters); 
    } 
}; 

cuando se utiliza asegúrese de que ha utilizado reserve() para asignar la memoria

Cuestiones relacionadas