2012-08-01 19 views
8

De la documentación CPP para std::vector, veo esto:C++ STL vector: push_back tomando como referencia

void push_back (const T& x); 

entiendo que push_back crea una copia del objeto que me pase. Pero, ¿por qué es la firma const T& ? Al mirar esto, inicialmente pensé que toma una referencia const de cualquier objeto que empuje al vector.

+0

Haré eso. Me di cuenta de eso solo ayer y lo estoy haciendo desde entonces. ¡Gracias! – sachin2182

Respuesta

12

La otra opción sería

void push_back(T x); 

, es decir, teniendo x por valor. Sin embargo, esto (en C++ 03) daría como resultado la creación de una copia adicional de x (la copia en los argumentos es push_back). Tomar x por const reference lo evita.

Veamos la pila para una llamada v.push_back(T()) tomado por valor:

v.push_back(T());      // instance of T 
void std::vector<T>::push_back(T x) // copy of T 
new (data_[size_ - 1]) T(x)   // copy of copy of T 

Tomando como referencia const obtenemos:

v.push_back(T());        // instance of T 
void std::vector<T>::push_back(const T &x) // const reference to T 
new (data_[size_ - 1]) T(x)     // copy of T 

En C++ 11 sería posible (aunque innecesaria) para tomar x por valor y usar std::move para moverlo al vector:

v.push_back(T());        // instance of T 
void std::vector<T>::push_back(T x)   // copy of T 
new (data_[size_ - 1]) T(std::move(x))  // move the copy of T 
+1

Aún es preferible que tome 'T const &' en C++ 11 (junto con una sobrecarga 'T &&'), ya que no todos los objetos se pueden mover de manera eficiente. –

7

El object que empuja se pasa por referencia para evitar extra copy. Que una copia se coloca en el vector.

7

Solo para aclarar la "copia adicional" que describe @ecatmur, si push_back recibió su argumento por valor, lo que sucedería sería que comenzaría con su objeto. Una copia de eso pasará a push_back como su parámetro. Entonces push_back crearía una copia de que poner en el propio vector.

Dado que la implementación real de push_back recibe su argumento por referencia, (push_back) crea el nuevo objeto en el vector directamente como una copia de su objeto original.

Como ya se mencionó, sí, con C++ 11 usando la semántica de movimiento, sería posible (aunque probablemente no particularmente ventajoso) pasar el argumento por valor, y luego mover el valor de ese argumento al nuevo objeto en el vector. Si lo que estaba poniendo en el vector era, por ejemplo, una cadena que contiene un puntero y un par de campos de "contabilidad" (cantidad de memoria asignada, cantidad de memoria actualmente en uso), sería casi como eficiente como pasar una referencia, porque un movimiento puede hacer una copia superficial; copie los valores del puntero y del libro, en lugar de todos los datos a los que apunta. Sin embargo, si el objeto en cuestión tenía todos sus datos directamente (es decir, no un puntero), un movimiento sería tan lento como una copia.

Pasando por referencia, evita todo que copia, por lo que incluso para algo así como una cadena, generalmente es más rápido (para un caso como este el objeto original no puede ser invalidado). También tiene la menor ventaja de trabajar con C++ 98/03, no solo con C++ 11.