2011-08-13 10 views
9

me pregunto si he entendido correctamente emplace_backC++ 0x emplace_back con productos que no copiable

#include <vector> 
using namespace std; 

struct Hero { 
    Hero(const string&) {} 
    Hero(const char*) {} 
    Hero(int) {} 
    // forbid a clone: 
    Hero(const Hero&) = delete; 
    Hero& operator=(const Hero&) = delete; 
}; 

int main() { 
    vector<Hero> heros1 = { "Bond", "Hulk", "Tarzan" }; // ERR: copies? 

    vector<Hero> heros; 
    heros.emplace_back(5);    // ERR: copies 
    heros.emplace_back(string("Bond")); // ERR: copies 
    heros.emplace_back("Hulk");   // ERR: copies 
} 

Por lo tanto, estoy realmente preguntando si he entendido emplace_back incorrectamente: Yo sin embargo sería evitar hacer una copia de Hero, porque crea el artículo en el lugar.

¿O es un error de implementación en mi g ++ - 4.7.0?

+2

Ya no es C++ 0x. ¡Es solo C++ ahora! ':)' –

Respuesta

6

es necesario definir un constructor movimiento y mover a la cesión del operador, así:

struct Hero { 
    Hero(const string&) {} 
    Hero(const char*) {} 
    Hero(int) {} 

    Hero(Hero&&) {} 
    Hero& operator=(Hero&&) { return *this; } 

    // forbid a clone: 
    Hero(const Hero&) = delete; 
    Hero& operator=(const Hero&) = delete; 
}; 

Esto permite que los valores de tipo de héroe que se mudaron a la función. Mover es generalmente más rápido que copiar. Si el tipo no se puede copiar ni mover, entonces no puede usarlo en un std::vector.

+1

También debe tener en cuenta que estos se generarán para usted si faltan, por lo que el código compilado y ejecutado –

+0

es absurdo. Si necesita un constructor de movimiento, entonces la ubicación no está reenviando al constructor ** inplace ** argumentos variódicos, todavía está haciendo una copia movida. Eso haría a emplace_back completamente inútil – lurscher

+2

@lurscher Para ser utilizado en un 'std :: vector', los objetos deben ser copiables o movibles. –

3

Uh ... Lo tengo.

Si forbit a copia los Hero s, debo permitir que movimiento, si quiero ponerlos en contenedores. Que tonto de mi parte.

struct Hero { 
    Hero(const string&) {} 
    Hero(const char*) {} 
    Hero(int) {} 
    // no clone: 
    Hero(const Hero&) = delete; 
    Hero& operator=(const Hero&) = delete; 
    // move only: 
    Hero(Hero&&) {} 
    Hero& operator=(Hero&&) {} 
}; 

Y todos los ejemplos a excepción de la lista de inicialización trabajo.

+7

Tenga en cuenta que 'emplace_back' en sí mismo * no * requiere que el tipo sea movible; construye el elemento in situ como lo pensó. Sin embargo, 'std :: vector' * en general * requiere que su tipo de elemento sea móvil o que pueda copiarse, de lo contrario no podría crecer según sea necesario. – JohannesD

4

No hay error de implementación; no proporcionó un constructor de movimientos.

+0

¡Fuiste rápido! Estaba escribiendo mi propia respuesta ;-) – towi