2011-10-11 4 views
5

Dans mon application, j'ai besoin de stocker une petite collection de données temporaires. Dans ces données temporaires, je veux stocker une référence à une autre classe et comme il ne peut pas être un nullptr, j'utilise une référence.Effacer un fichier std :: vector nécessite un opérateur d'affectation. Pourquoi?

Utilise un vecteur pour stocker les données (je n'ai pas trop de données donc le vecteur est bon).

Remplir le vecteur, et itérer par dessus fonctionne correctement, mais effacer le vecteur semble poser problème.

C'est un code simplifié montrant le problème:

class Department 
    { 
    }; 

class Person 
    { 
    public: 
     Person (const Department &dept) 
     : m_dept(dept) 
     , m_salary(1000) 
     {} 
    private: 
     const Department &m_dept; 
     double m_salary; 
    }; 

#include <vector> 

int main() 
{ 
std::vector<Person> persons; 

Department dept1; 
Department dept2; 

persons.push_back (Person(dept1)); 
persons.push_back (Person(dept2)); 

persons.clear(); 
} 

Tout compile et fonctionne parfaitement sauf la dernière déclaration. Effacement du vecteur donne ce message d'erreur (Visual Studio 2010):

C:\DevStudio\Vs2010\VC\INCLUDE\xutility(2526) : error C2582: 'operator =' function is unavailable in 'Person' 
     C:\DevStudio\Vs2010\VC\INCLUDE\xutility(2547) : see reference to function template nstantiation '_OutIt std::_Move<_InIt,_OutIt>(_InIt,_InIt,_OutIt,std::_Nonscalar_ptr_iterator_tag)' being compiled 
     with 
     [ 
      _OutIt=Person *, 
      _InIt=Person * 
     ] 
     C:\DevStudio\Vs2010\VC\INCLUDE\vector(1207) : see reference to function template instantiation '_OutIt std::_Move<Person*,Person*>(_InIt,_InIt,_OutIt)' being compiled 
     with 
     [ 
      _OutIt=Person *, 
      _InIt=Person * 
     ] 
     C:\DevStudio\Vs2010\VC\INCLUDE\vector(1190) : while compiling class template member function 'std::_Vector_iterator<_Myvec> std::vector<_Ty>::erase(std::_Vector_const_iterator<_Myvec>,std::_Vector_const_iterator<_Myvec>)' 
     with 
     [ 
      _Myvec=std::_Vector_val<Person,std::allocator<Person>>, 
      _Ty=Person 
     ] 
     test.cpp(21) : see reference to class template instantiation 'std::vector<_Ty>' being compiled 
     with 
     [ 
      _Ty=Person 
     ] 

La raison semble être que la mise en œuvre de std :: vector :: appels clairs std :: vector :: erase, qui appelle la méthode _move , qui semble avoir besoin de l'opérateur d'affectation.

Pourquoi ne peut pas la méthode claire simplement:

  • appel du destructor pour tous les éléments du vecteur
  • définir la taille du vecteur à zéro

Le plus drôle est que quand je utilisez std :: list au lieu de std :: vector, le code se compile correctement.

Pourquoi est-ce?

Est-ce que d'autres compilateurs ont aussi ce problème?

+1

En note, les références en C++ ne peuvent pas être nulles et ne peuvent pas être réassemblées. Sauf si vous voulez les deux propriétés, vous ne devriez pas les utiliser. –

Répondre

11

Toute classe placée dans un vecteur nécessite un opérateur d'affectation de copie (ou au moins une affectation de mouvement opérateur en C++ 11). C'est juste une question de qualité de la mise en œuvre lorsque vous obtenez l'erreur.

2

Avez-vous réellement commenté l'appel clear(), et essayé de le compiler? Je suis assez sûr (et mon compilateur est d'accord avec moi) que le push_back cause cela (en raison de la copie nécessaire des données existantes)

+0

Le message d'erreur indique qu'il est nécessaire dans 'erase' qui est probablement appelé par' clear' ('clear = effacer (begin, end)'). Même si l'assignation ne sera probablement pas utilisée pour tout effacer, la fonction doit encore être compilée. L'assignabilité est une exigence de conteneur de toute façon. - J'imagine que push_back peut être implémenté en termes de constructeur de copie. – visitor

+0

En commentant l'appel clair, tout fonctionne parfaitement. – Patrick

Questions connexes