2010-08-06 21 views
5

Podría alguien explicar por qué me sale un error de compilación aquí - error C2558: clase 'std :: auto_ptr < _Ty>': no ​​hay copia de constructor disponible o copia constructor se declara 'explícito'Ningún constructor de copia disponible o el constructor de copia se declara 'explícito'

#include <memory> 
#include <vector> 
#include <string> 
template<typename T> 
struct test 
{ 
    typedef std::auto_ptr<T> dataptr; 
    typedef std::auto_ptr< test<T> > testptr; 
    test(const T& data): 
    data_(new T(data)) 
    { 
    }; 
    void add_other(const T& other) 
    { 
     others_.push_back(testptr(new test(other))); 
    } 
private: 
    dataptr data_; 
    std::vector<testptr> others_; 
}; 

int main(int argc, char* argv[]) 
{ 
    test<std::string> g("d"); 

    //this is the line that causes the error. 
    g.add_other("d"); 

    return 0; 
} 
+0

Ha pasado un tiempo desde que hice C++, pero ¿no debería ser 'g = prueba (" d ");'? –

+0

@Jesse J: Ambos están bien. Las dos formas tienen un comportamiento ligeramente diferente que en todos los casos menos diabólicos dan el mismo resultado. Técnicamente, su método creará una clase de prueba y luego la asignará a g, en lugar de simplemente inicializar g. Esto solo se convierte en un problema cuando tiene comportamientos personalizados de copia/asignación/inicio. – Akusete

+0

Gracias a todos. Respuestas realmente informativas. – Carl

Respuesta

6

Básicamente, un std::auto_ptr no se puede utilizar de esta manera.

others_.push_back(testptr(new test(other))); 

requiere que un constructor de copia que tiene un const& existe y no existe tal constructor para std::auto_ptr. Esto es ampliamente visto como Lo bueno desde nunca debe usar std::auto_ptr en un contenedor! Si no entiende por qué ocurre esto, entonces read this article by Herb Sutter, particularmente la sección titulada "Cosas que no hacer, y por qué no hacerlas" aproximadamente 3/4 del total.

+1

Si los contenedores estándar tenían el mandato de usar 'swap' para copiar cosas, auto_ptr funcionaría. Y realmente me gustaría que lo fueran. En C++ 0x, ':: std :: unique_ptr' (que es muy parecido a' :: std :: auto_ptr') tampoco tiene un contructor de copia, y solo tiene un constructor de movimiento, y los contenedores estándar son obligatorios para usar el constructor de movimientos para mover sus contenidos, para que pueda almacenar ':: std :: unique_ptr' en ellos y hacer que funcione como se esperaba. – Omnifarious

+0

De hecho, es ilegal usar 'auto_ptr' en un contenedor porque los contenedores STL requieren que sus miembros tengan un comportamiento de copia" normal ". Auto_ptr no cumple ese requisito. –

+1

@Omnifarious: está mezclando shared_ptr con unique_ptr. Shared_ptr es un puntero inteligente contado de referencia, no uno con semántica de movimiento. –

4

No se puede crear contenedores de la biblioteca estándar de auto_ptr, ya que estamos tratando de hacer aquí:

std::vector<testptr> others_; 

ya que no tienen la semántica correcta. Tendrá que utilizar punteros ordinarios o un sabor diferente de puntero inteligente, como shared_ptr.

Cuestiones relacionadas