2017-09-11 4 views
7

I understand (at least I think I do) que les pointeurs peuvent être utilisés comme des itérateurs STL aléatoires.Effacement de vecteur STL via le pointeur

Pourquoi le code suivant n'est-il pas compilé à moins que je ne lance le pointeur vers un itérateur?

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

Pourquoi pensez-vous un pointeur vers l'élément est identique à un iterator ('std :: vector :: iterator')? – NathanOliver

+1

Quelle erreur obtenez-vous? –

+6

Alors que les itérateurs peuvent être implémentés à l'aide de pointeurs, un pointeur n'est pas automatiquement un itérateur. –

Répondre

12

Vous pouvez passer des pointeurs à algorithmes comme std::sort, std::find ou std::copy. Ce sont des modèles qui sont configurables pour tout ce qui fonctionne comme un itérateur approprié.

Cela ne signifie pas que les différents itérateurs se convertissent nécessairement les uns aux autres.

La méthode erase du conteneur std::vector<int> ne peut fonctionner qu'avec des itérateurs d'éléments du même vecteur. Comme on l'a souligné ce qui peut être mis en œuvre comme un pointeur, mais il est généralement pas, pour des raisons énoncées ici: C++ std::vector<>::iterator is not a pointer, why?

Tenir compte std::find:

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

Ici InputIt est un paramètre de modèle. Le modèle std::find fonctionnera avec n'importe quel type d'itérateur répondant aux exigences d'un input iterator, et dont le operator* renvoie quelque chose qui peut être comparé au type T. Les pointeurs fonctionnent bien ici. Comme Fire Lancer a fait remarquer correctement dans un commentaire, les deux first et last doivent être de type InputIt.

Maintenant, comparez cela à std::vector::erase:

iterator erase(const_iterator pos); 

Cela prend const_iterator, qui est l'un des typedefs de la classe std::vector. C'est un type particulier d'itérateur, pas un paramètre de modèle.

+1

Passer correctement ** les paires ** de pointeurs vers ces algorithmes est effectivement un type d'itérateur à accès aléatoire. Mais, vous ne pouvez toujours pas passer un pointeur et un itérateur vectoriel comme une "paire" à ceux-ci, même si le pointeur est à l'intérieur du vecteur. –

1

La définition de vector.erase(...) est

iterator erase(const_iterator pos);

Le const iterator est une classe en soi. Donc, s'il y avait une conversion d'un pointeur simple à cette classe, alors cela pourrait être fait. Mais je ne pense pas qu'il y en ait. Mais une chose est de l'utiliser dans un endroit où un itérateur est prévu, et un autre est d'utiliser dans les algorithmes.

Lorsqu'un iterator est requis, seul un itérateur peut être utilisé.

Dans les algorithmes, aucun iterator n'est attendu. Seul un objet pour lequel un Concept d'un iterator est satisfait (généralement un begin et end renvoie l'itérateur/pointeur requis).

+0

Les algorithmes attendent des itérateurs, pas des "objets pour lesquels un début/fin ..." peu importe. – juanchopanza

+1

Les algorithmes utilisent des modèles - les paramètres ne sont pas des types concrets de '' 'itérateur'''. Vous pouvez passer n'importe quel objet qui satisfait le concept d'un '' '' 'itérateur''' dans les fonctions. –

+0

Mon point précisément. Merci pour la réparation. – juanchopanza

0

Bien que les pointeurs sont itérateurs, ils ne sont pas les mêmes de type comme vecteur itérateurs (au moins ils ne doivent pas être).

Vous pouvez convertir un pointeur sur un élément d'un vecteur dans un itertor en utilisant iterator et l'arithmétique de pointeur comme celui-ci.

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

Cela ne fonctionne avec des conteneurs contigus comme std::vector ou std::array.