2017-09-11 91 views
7

I understand (at least I think I do) to wskaźniki mogą być używane jako losowe iteratory STL.Usuwanie wektorów STL za pomocą wskaźnika

Dlaczego następujący kod nie jest kompilowany, chyba że rzuciłem wskaźnik na iterator?

vector<int> v{1, 2, 3}; 
v.erase(&v[0]); 
+12

Dlaczego myślisz, że wskaźnik do elementu jest taki sam jak iterator ('std :: vector :: iterator')? – NathanOliver

+1

Jaki błąd dostałeś? –

+6

Podczas gdy iteratory mogą być implementowane za pomocą wskaźników, wskaźnik nie jest automatycznie iteratorem. –

Odpowiedz

12

można przekazać wskaźniki do algorytmów jak std::sort, std::find lub std::copy. Są to szablony konfigurowalne dla wszystkiego, co działa jako odpowiedni iterator.

Nie oznacza to, że różne iteratory muszą się nawzajem przekształcać.

Metoda erase kontenera std::vector<int> może pracować z iteratorami tylko z elementami tego samego wektora. Jak zostało wskazane może być realizowany jako wskaźnik, ale zwykle nie jest, z powodów podanych tutaj: C++ std::vector<>::iterator is not a pointer, why?

Rozważmy std::find:

template< class InputIt, class T > 
InputIt find(InputIt first, InputIt last, const T& value); 

Tutaj InputIt jest parametrem szablonu. Szablon std::find będzie działał z każdym typem iteratora, który spełnia wymagania input iterator, a którego operator* zwraca coś, co można porównać do typu T. Wskaźniki działają tutaj dobrze. Jak zauważył Fire Lancer w komentarzu, zarówno first i last musi być typu InputIt.

teraz porównać do std::vector::erase:

iterator erase(const_iterator pos); 

To trwa const_iterator, który jest jednym z typedefs klasy std::vector. Jest to jeden szczególny typ iteratora, a nie parametr szablonu.

+1

Mijanie ** par ** wskaźników do tych algorytmów jest efektywnie typem iteratora dostępu losowego. Ale nadal nie można przekazać wskaźnika i wektora iteratora jako "pary" do nich, nawet jeśli wskaźnik znajduje się wewnątrz wektora. –

1

Definicja vector.erase(...) jest

iterator erase(const_iterator pos);

const iterator to klasa sama w sobie. Więc jeśli nastąpiła konwersja zwykłego wskaźnika na tę klasę, to można to zrobić. Ale nie sądzę, że istnieje.

Ale należy go używać w miejscu, w którym oczekuje się iteratora, a innego używać w algorytmach.

Jeśli wymagany jest iterator, można użyć tylko iteratora.

W algorytmach nie jest oczekiwany kod iterator. Tylko obiekt, dla którego usatysfakcjonowany jest obiekt (zwykle begin i end, zwraca wymagany iterator/wskaźnik).

+0

Algorytmy oczekują iteratorów, a nie "obiektów, dla których początek/koniec ..." cokolwiek. – juanchopanza

+1

Algorytmy używają szablonów - parametry nie są konkretnymi typami '' 'iteratora'''. Możesz przekazać dowolny obiekt, który spełnia Koncepcję "iteratora" do funkcji. –

+0

Dokładnie. Dzięki za naprawę. – juanchopanza

0

Chociaż wskaźniki są iteratory, nie są one takie same typ jak wektor iteratory (przynajmniej nie muszą być).

Możesz przekonwertować wskaźnik na element wektora na itertor używając iteratora i arytmetyki wskaźnika w ten sposób.

std::vector<int> v{1, 2, 3}; 

int* p = &v[0]; // a pointer 

auto v_iter = v.begin() + std::distance(v.data(), p); // an equivalent vector::iterator 

v.erase(v_iter); 

Zadziała tylko z sąsiadujących ze sobą pojemników, takich jak std::vector lub std::array.