2012-05-31 14 views
6

Wyobraź sobie, że class C ma zmienną składową m_MyList typu std::vector, w której chcę przechowywać obiekty typu MyClass. C ma dwie funkcje, które dodają lub usuwają obiekty w m_MyList. m_MyList należy również udostępnić użytkownikom o wartości C, ponieważ muszą oni przeczytać kolekcję obiektów o numerach MyClass. Zewnętrzny czytnik kolekcji nie będzie miał możliwości zmiany kolekcji, dlatego obiekty MyClass są własnością tylko C.Czy powinienem używać std :: unique_ptr <T> w zmiennej std :: vector member w mojej klasie?

Teraz moje pytanie: W stylu C++ 11, jaki jest najlepszy T do przechowywania w wektorze? Możliwości wydają się być:

  • std::vector<MyClass>
  • std::vector<MyClass*>
  • std::vector<unique_ptr<MyClass>> korzystając std:move pchnąć unique_ptr do vector
+3

Rozwiązanie "unique_ptr" tak naprawdę niczego nie kupuje, chyba że obiekty są nieoprawione. Wersja surowego wskaźnika jest wręcz szkodliwa. Po prostu przejdź do prostego rozwiązania. – jalf

+0

Jak duży jest obiekt 'MyClass' i ile planujesz przechowywać? Czy będzie dużo pojedynczych wstawek? – RedX

Odpowiedz

13

Jeśli MyClass obiekty są własnością C, to najlepiej opcja byłaby najprostsza:

std::vector<MyClass> 

Jedynym powodem, dla którego mogłem się przekonać do korzystania z std::unique_ptrs jest tutaj, jeśli chcesz zachować wskaźniki do klasy bazowej dla polimorfizmu. W tym przypadku unique_ptrs służą do uwalniania zasobów po zniszczeniu wektora. Jednak interfejs C nie powinien przenosić prawa własności na klientów.

+5

'MyClass' może być obiektem, który jest kosztowny w przenoszeniu/kopiowaniu. Za pomocą wskaźnika można zmienić rozmiar wektora bez konieczności kopiowania dużej ilości pamięci. –

+1

@ edA-qamort-ora-y to prawda, ale jest niezależna od własności i klientów i tak dalej, więc założyłem, że rozważanie wykracza poza zakres pytania. – juanchopanza

+1

Innym powodem używania dowolnego rodzaju odwołania jako członka klasy jest upewnienie się, że nagłówek nie ujawnia szczegółów tego elementu, podczas gdy plik jednostki (cpp) o tym wie. W rzeczywistości jest to dobre dla izolacji. W tym przypadku wektor wymaga zdefiniowania MyClass przed zdefiniowaniem elementu. Musisz więc dołączyć kod MyClass. W niektórych przypadkach nie chcesz tego. Biorąc to pod uwagę, mają inne koszty pamięci i zarządzania, więc wybór jest bardzo zależny od kontekstu. – Klaim

11

Surowe wskaźniki (std::vector<MyClass*>) są niepoprawne, jeśli C jest właścicielem obiektów. Pozostałe dwa są bardzo podobne z następujących kompromisów:

  • std::vector<MyClass> - wymaga MojaKlasa być copyable i/lub przenieść-stanie
  • std::vector<unique_ptr<MyClass>> - Wymaga (dodatkowe) Przydziały dynamiczne

rodzaj operacji wykonywanych na kontenerze może również być istotny. Aby przyjąć skrajny przykład, jeśli MyClass jest duży, a kontener jest wielokrotnie tasowany, lepszym wyborem będzie unique_ptr.

+0

Każdy element 'std :: vector' jest umieszczony w wolnym sklepie, więc powiedzenie" wymaga dynamicznych alokacji ", jak to jest złe, to rodzaj niewłaściwej nazwy ... – rubenvb

+2

@rubenvb: wektor wymaga tylko jednej alokacji dynamicznej w tym samym czasie (lub krótko 2 podczas realokacji). Dlatego nie wymaga dynamicznych przydziałów ;-) Jeśli 'MyClass' jest wystarczająco mały, w końcu zauważysz różnicę. Przypuszczam, że lepiej powiedzieć "wymaga więcej nakładów w alokacjach dynamicznych". To źle, jeśli piszesz dodatkowy kod wyłącznie w celu marnowania pamięci. To * może * być złe, jeśli 'MyClass' nie jest konstruktywny, a wprowadzasz alokacje dynamiczne w miejscach, w których w przeciwnym razie by się nie wydarzyły, wprowadzając wyjątki. –

+0

Dynamiczna alokacja każdego pojedynczego obiektu nie tylko zabiera więcej pamięci, zwiększa fragmentację i powoduje więcej braków w pamięci podręcznej danych. W większości kodu będzie to całkowicie niezauważalne, ale jak mówi Steve - nie pisz więcej, aby kod nieco się pogorszył. –

Powiązane problemy