2011-10-11 16 views
5

W mojej aplikacji muszę przechowywać niewielką kolekcję danych tymczasowych. W tych tymczasowych danych chcę zapisać odniesienie do innej klasy i ponieważ nie może to być nullptr, używam odwołania.Usuwanie std :: vector wymaga operatora przypisania. Czemu?

Używa wektora do przechowywania danych (nie mam zbyt dużo danych, więc wektor jest w porządku).

Wypełnianie wektora i powtarzanie go działa dobrze, ale czyszczenie wektora wydaje się stwarzać problemy.

To jest jakiś uproszczony kod pokazujący problem:

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(); 
} 

Wszystko kompiluje i działa doskonale z wyjątkiem ostatniego oświadczenia. Usuwanie wektor daje ten komunikat o błędzie (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 
     ] 

Powodem wydaje się, że realizacja std :: vector :: wyraźne rozmowy std :: vector :: erase, który wywołuje metodę _Move , który wydaje się potrzebować operatora przypisania.

Dlaczego nie można po prostu klarowny sposób:

  • wywołanie destruktora dla wszystkich elementów w wektorze
  • ustawić rozmiar wektora do zera

Najśmieszniejsze jest to, że kiedy użyj std :: list zamiast std :: vector, kod kompiluje się poprawnie.

Dlaczego tak jest?

Czy inne kompilatory również mają ten problem?

+1

Uwaga: odniesienia w C++ nie mogą być puste i nie można ich ponownie wstawić. Jeśli nie chcesz obu właściwości, nie powinieneś ich używać. –

Odpowiedz

11

Każda klasa umieszczona w wektorze wymaga operatora przypisania kopii (lub przynajmniej przeniesienia przeniesienia operator w C++ 11). Jest to tylko kwestia jakości implementacji, gdy faktycznie dostaniesz błąd.

2

Czy rzeczywiście skomentowałeś wywołanie clear() i próbowałeś je skompilować? Jestem prawie pewien (i mój kompilator zgadza się ze mną), że push_back to powoduje (ze względu na potrzebne kopiowanie istniejących danych).

+0

Komunikat o błędzie mówi, że jest potrzebny w 'Wymaż', który prawdopodobnie jest wywoływany z' wyczyszczenia' ('wyczyść = wymaż (początek, koniec)'). Chociaż przypisanie prawdopodobnie nie będzie używane do kasowania wszystkiego, funkcja nadal musi się skompilować. Przypisanie i tak jest wymaganiem kontenera. - push_back, jak sobie wyobrażam, można zaimplementować pod kątem konstruktora kopii. – visitor

+0

Podczas komentowania wyraźnego połączenia wszystko działa idealnie. – Patrick

Powiązane problemy