2011-09-11 41 views
17

¿Cuál es la forma correcta de empujar un nuevo elemento de objeto en un std::vector? Quiero que los datos se asignen en el vector. ¿Esto copiará el objeto newradio en el vector y luego se deshará de newradio cuando se sale del alcance (por ejemplo, de la pila)?C++ vector push_back

vector<Radio> m_radios; 
Radio newradio(radioNum); 
m_radios.push_back(newradio); 

Y luego, cuando me libero del objeto que contiene m_radios, se esta libre de toda la memoria asignada por el vector?

Respuesta

29

std::vector gestiona su propia memoria. Eso significa que, cuando se invoca el destructor de un vector, se libera la memoria retenida por el vector. std::vector también invoca el destructor de un objeto cuando se elimina (a través de erase, pop_back, clear o el destructor del vector).

Al hacer esto:

Radio newradio(radioNum); 
m_radios.push_back(newradio); 

se agrega una copia de newradio (creada usando Radio 's constructor de copia) al vector. newradio se destruirá cuando salga del alcance, y la copia se destruirá cuando se elimine del vector (como para cualquier objeto).

Ese es un punto importante: std::vector sólo almacena copias de un objeto, lo que significa que el objeto debe tener un constructor de copia significativa (y un operador de asignación, pero eso es otro tema). Si tiene un vector de punteros, se copiará el puntero y no a qué apunta. Tenga en cuenta que este comportamiento es el mismo para cada contenedor estándar (como std::list o std::set).

Como regla general, si no está utilizando punteros, entonces no tiene que preocuparse de liberar la memoria usted mismo.

En C++ 11, los contenedores estándar de la mayoría (incluyendo vector) tienen un método de emplace_back que construye un objeto en lugar en el extremo del recipiente. Toma un montón de parámetros y llama al constructor que mejor se ajusta a esos parámetros (o falla si no existe ese constructor), utilizando dicho constructor para crear el objeto, sin ninguna copia, al final del contenedor. Por lo tanto, el código anterior podría ser reescrita como:

m_radios.emplace_back(radioNum); // construct a Radio in place, 
           // passing radioNum as the constructor argument 

También en C++ 11, los contenedores están normalmente mover consciente, por lo que ya no requieren objetos para ser copiable: si son móvil, entonces el contenedor moverá su contenido según sea necesario (como durante las reasignaciones, por ejemplo). Los tipos que se pueden copiar aún son necesarios si quiere copiar el vector.

+3

Aunque correcta en el momento, esta respuesta podría utilizar una actualización mencionar 'emplace_back' –

+0

Muy buen punto Sr. Pato. –

0

Yup, radioNum será copiado en m_radios. Siempre que no esté desasignando punteros cuando se produce newradio.~Radio(); (fuera del alcance), está bien. Si m_radios, o una subclase utiliza punteros, deberá hacer el cambio a smart pointers (shared_ptr).

Cuando m_radios sale del alcance, se llama automáticamente al destructor y se libera todo el contenido std::vector.

1

Sí empujando newRadio insertará una copia del objeto Radio en el vector. Tampoco es necesario que libere el vector porque solo es local, por lo que se destruirá una vez que se encuentre fuera de su alcance. Si, por ejemplo, usted escribió

vector<Radio> *m_radios = new vector<Radio>(); 

Luego tendría que liberar esa memoria llamando al vector destructor manualmente.

3

push_back() almacenará una copia de su argumento dentro del vector. Siempre que Radio implemente la semántica de valor adecuada, no habrá problemas con ella.

0

Además de las otras respuestas que verificar que el objeto se copia en el contenedor cuando se utiliza push_back a través de las llamadas al constructor de copia, es posible que también tenga en cuenta la nueva funcionalidad añadida emplace_back con c++0x.

Llamar a emplace_back le permite omitir la creación de cualquier objeto temporal y hacer que el objeto se construya in situ dentro del contenedor directamente. emplace_back es una función de plantilla varardic que acepte los parámetros que pasaría al constructor de su objeto, por lo que en este caso:

std::vector<Radio> m_radios; 
m_radios.emplace_back(radioNum); 

no creará ningún temporales intermedios. Esto puede ser útil si sus objetos son caros de copiar.

Espero que esto ayude.

0

De manera predeterminada, std :: vector administra la memoria utilizando el constructor de copia de la clase subyacente. Por lo tanto, actúa un poco como si el elemento vector fuera una variable local (cuando el vector sale del alcance, el elemento se destruye).

Si no desea este comportamiento, puede utilizar un vector de puntero o boost :: ptr_vector en su lugar.

1

Prueba esto:

#include<iostream.h> 
#include<vector.h> 

class base 
{ 
int i; 
public: 

    base(int z=0){i=z;cout<<"okk constructor "<<i<<" called\n";} 
    base(const base& b1){i=b1.i;cout<<"copy constructor "<<i<<" called\n";} 
    void display(){cout<<" val is "<<i<<" \n";} 
    ~base(){cout<<"destructor of "<<i<<" base called\n";} 
}; 


    int main() 
    { 
     cout<<"before anything\n"; 
     vector<base> basev; 
     base baseobj1(1); 
     base baseobj2(2); 
     base baseobj3(3); 
     base baseobj4(4); 
     base baseobj5(5); 
     base baseobj6(6); 
     base baseobj7(7); 
     base baseobj8(8); 
     base baseobj9(9); 
     base baseobj10(10); 


     basev.push_back(baseobj1); 
     cout<<"second push back\n"; 
     basev.push_back(baseobj2); 
     cout<<"third push back\n"; 
     basev.push_back(baseobj3); 
     cout<<"fourth push back\n"; 
     basev.push_back(baseobj4); 
     cout<<"fifth push back\n"; 
     basev.push_back(baseobj5); 
     cout<<"sixth push back\n"; 
     basev.push_back(baseobj6); 
     cout<<"seventh push back\n"; 
     basev.push_back(baseobj7); 
     cout<<"eighth push back\n"; 
     basev.push_back(baseobj8); 
     cout<<"ninth push back\n"; 
     basev.push_back(baseobj9); 
     cout<<"10th push back\n"; 
     basev.push_back(baseobj10); 
     cout<<"after all push back\n"; 


     cout<<"before clear\n"; 
     basev.clear(); 
     cout<<"after clear\n"; 


} 

de salida:

before anything 
okk constructor 1 called 
okk constructor 2 called 
okk constructor 3 called 
okk constructor 4 called 
okk constructor 5 called 
okk constructor 6 called 
okk constructor 7 called 
okk constructor 8 called 
okk constructor 9 called 
okk constructor 10 called 
copy constructor 1 called 
second push back 
copy constructor 1 called 
copy constructor 2 called 
destructor of 1 base called 
third push back 
copy constructor 1 called 
copy constructor 2 called 
copy constructor 3 called 
destructor of 1 base called 
destructor of 2 base called 
fourth push back 
copy constructor 4 called 
fifth push back 
copy constructor 1 called 
copy constructor 2 called 
copy constructor 3 called 
copy constructor 4 called 
copy constructor 5 called 
destructor of 1 base called 
destructor of 2 base called 
destructor of 3 base called 
destructor of 4 base called 
sixth push back 
copy constructor 6 called 
seventh push back 
copy constructor 7 called 
eighth push back 
copy constructor 8 called 
ninth push back 
copy constructor 1 called 
copy constructor 2 called 
copy constructor 3 called 
copy constructor 4 called 
copy constructor 5 called 
copy constructor 6 called 
copy constructor 7 called 
copy constructor 8 called 
copy constructor 9 called 
destructor of 1 base called 
destructor of 2 base called 
destructor of 3 base called 
destructor of 4 base called 
destructor of 5 base called 
destructor of 6 base called 
destructor of 7 base called 
destructor of 8 base called 
10th push back 
copy constructor 10 called 
after all push back 
before clear 
destructor of 1 base called 
destructor of 2 base called 
destructor of 3 base called 
destructor of 4 base called 
destructor of 5 base called 
destructor of 6 base called 
destructor of 7 base called 
destructor of 8 base called 
destructor of 9 base called 
destructor of 10 base called 
after clear 
destructor of 10 base called 
destructor of 9 base called 
destructor of 8 base called 
destructor of 7 base called 
destructor of 6 base called 
destructor of 5 base called 
destructor of 4 base called 
destructor of 3 base called 
destructor of 2 base called 
destructor of 1 base called 
+2

Por favor, edite su respuesta y formatee el código para que sea legible. – kleopatra

+1

No entiendo qué está pasando en este código: S podría alguien explicar? Gracias –

Cuestiones relacionadas