2009-07-11 13 views

Odpowiedz

65

Odzyskiwanie element wskaźnikiem jest O (n) działanie na listę, na której znajduje się co std::list IS. Więc zdecydowano, że zapewnienie operator[] byłoby zwodnicze, ponieważ ludzie będą kuszeni, aby aktywnie wykorzystywać ją, a potem by zobaczyć kod jak:

std::list<int> xs; 
for (int i = 0; i < xs.size(); ++i) { 
    int x = xs[i]; 
    ... 
} 

który wynosi O (n^2) - bardzo nieprzyjemny. Tak więc standard ISO C++ wspomina, że ​​wszystkie sekwencje STL, które obsługują operator[], powinny robić to w zamortyzowanym stałym czasie (23.1.1 [lib.sequence.reqmts]/12), co jest możliwe dla vector i deque, ale nie list.

W przypadkach, w których rzeczywiście potrzebują tego rodzaju rzeczy, można użyć std::advance algorytmu:

int iter = xs.begin(); 
std::advance(iter, i); 
int x = *iter; 
+0

Więc, w zasadzie, chodzi tylko o zapobieganie popełnianiu błędów przez ludzi? –

+17

tak.Albo nie składanie obietnic, których nie możesz dotrzymać. W STL operator [] obiecuje * wydajny * dostęp do dowolnych elementów. – jalf

+0

I dziękuje Pavel za standardowe odniesienie C++! –

3

To nie byłoby zbyt trudne (dla realizatora), ale byłoby to zbyt trudne w czasie wykonywania, ponieważ wydajność będzie straszny w większości przypadków. Zmuszenie użytkownika do przejścia przez każdy link sprawi, że będzie bardziej oczywiste, co się tam dzieje, niż "myList [102452]".

+0

opracowanie operator bitowy [] jest stałe w czasie operacji we wszystkich innych miejscach nie jest używany. Nadanie tej samej nazwy operacji O (n) byłoby niespójne i mylące. – dmckee

+0

To jest O (log n) na mapie, ale rozumiem. –

+0

Na mapie to nie jest zdecydowanie pozycyjny wskaźnik, który jest dość oczywista - może z wyjątkiem gdy klucz mapa jest liczbą całkowitą, ale jeśli jesteś mylące pozycyjną dostęp z klucz wyszukiwania, masz już dużo większe problemy;) –

1

Myślę, że znalazłem odpowiedź w innym SO zakładać Extending std::list

„swojego operatora [] to czas O (N) "- to właśnie dlatego jest niewpisane w standardzie std :: list <>. - Michael Burr 14 grudnia o 17:29

Ale czy to jedyny powód?

EDIT: Wydaje się jednak, jak ludzie wspomniano jest to bardziej kwestia spójności w zakresie wydajności następnie ściśle wydajności.

+0

Masz na myśli, że to nie wystarczający powód? :-) –

+0

To jest. Patrząc gdzie indziej, .NET 'LinkedList' nie dostarcza indeksu z tych samych powodów - jest po prostu zbyt zwodniczy. Tradycyjnie, gdy coś ma indeksujący położenie, przyjmuje się, że operacja to O (1). –

0

Faktycznie, nie ma absolutnie żadnego powodu, aby nie dostarczyć operator [] lub przynajmniej sposób na (int), ponieważ z dwóch powodów:

  • Jest podwójna lista powiązane, więc trzeba się poruszać z prędkością większość size()/2 umieszcza twój iterator w celu uzyskania indeksu, a koszty wewnętrznego utrzymywania kilku kolejnych stałych iteratorów są bardzo niskie. I na koniec biblioteka Qt dostarcza operatorowi [] i at, i nie widzę kosztów wydajności z niego korzystających.
  • zmuszanie ludzi coś nie do wykorzystania jest bardzo złe programowanie nawyk, bo lista będzie znacznie użyteczny pojemnik, jeśli masz „swobodnego dostępu” w pobliżu połączonego dostępu, istnieje przykłady odmiany, gdy trzeba mieć dostęp, w zależności na który punkt kontrolny.
+0

Czy to jest czysto bazowe według twojej opinii, czy stworzyłeś niezły scenariusz testowy, w którym pokazujesz, że twoja niestandardowa implementacja 'std :: list :: operator []' jest wydajna? (BTW, według Stroustrup standardowym kontenerem, którego powinieneś użyć, jest 'std :: vector'). – Zeta

Powiązane problemy