2010-08-06 6 views
5

Quelqu'un pourrait-il expliquer pourquoi j'obtiens une erreur de compilation ici - erreur C2558: class 'std :: auto_ptr < _Ty>': aucun constructeur de copie disponible ou constructeur de copie est déclarée 'explicite'Aucun constructeur de copie disponible ou constructeur de copie n'est déclaré 'explicite'

#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

Ça fait longtemps que je n'ai pas fait de C++, mais ça ne devrait pas être 'g = test (" d ");'? –

+0

@Jesse J: Les deux sont ok. Les deux voies ont un comportement légèrement différent qui, dans tous les cas sauf les plus diaboliques, donne le même résultat. Techniquement, votre méthode créera une classe de test, puis l'assignera à g, plutôt que d'initialiser g elle-même. Cela devient seulement un problème lorsque vous avez des comportements de copie/affectation/init personnalisés. – Akusete

+0

Merci à tous. Des réponses vraiment informatives. – Carl

Répondre

6

Fondamentalement, un std::auto_ptr ne peut pas être utilisé de cette manière.

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

exige qu'un constructeur de copie qui prend un const& existe et aucun constructeur existe pour std::auto_ptr. Ceci est largement considéré comme bonne chose depuis vous ne devriez jamais utiliser std::auto_ptr dans un conteneur! Si vous ne comprenez pas pourquoi c'est le cas, puis read this article by Herb Sutter, en particulier la section intitulée "Les choses à ne pas faire, et pourquoi ne pas les faire" environ 3/4 du chemin à travers.

+1

Si les conteneurs standard étaient mandatés pour utiliser swap pour copier des choses, auto_ptr fonctionnerait. Et je souhaite vraiment qu'ils étaient. En C++ 0x, ':: std :: unique_ptr' (qui ressemble beaucoup à' :: std :: auto_ptr') n'a pas non plus de constructeur de copie, et n'a qu'un constructeur de déplacement, et les conteneurs standards sont obligatoires utiliser le constructeur de déplacement pour déplacer leur contenu, vous pouvez donc y stocker ':: std :: unique_ptr' et le faire fonctionner comme prévu. – Omnifarious

+0

En fait, il est illégal d'utiliser 'auto_ptr' dans un conteneur parce que les conteneurs STL exigent que leurs membres aient un comportement de copie" normal ". Auto_ptr ne répond pas à cette exigence. –

+1

@Omnifarious: Vous mélangez shared_ptr avec unique_ptr. Shared_ptr est un pointeur intelligent compté par référence, pas un avec une sémantique de déplacement. –

4

Vous ne pouvez pas créer des conteneurs de la bibliothèque standard de auto_ptr, comme vous essayez de faire ici:

std::vector<testptr> others_; 

car ils n'ont pas la sémantique correcte. Vous devrez utiliser des pointeurs ordinaires ou un autre type de pointeur intelligent, tel que shared_ptr.

Questions connexes