2017-01-25 4 views
6

Angew made a comment, что vector с использованием необработанного указателя, так как это тип итератора. Это меня бросило в петлю.Использует ли указатель в качестве контейнера Итератор Нарушает стандарт

Я начал исследовать его и обнаружили, что требование vector итераторов было только то, что они "Random Access Iterators", для которых явно указано, что указатели квалифицироваться:

указатель на элемент массива удовлетворяет всем требованиям

Это единственная причина, по которой компиляторы даже предоставляют итераторы для vector для целей отладки, или есть ли на самом деле требование, которое я пропустил на vector?

+0

Скорее всего, для согласованности с остальной частью стандартной библиотеки. 'template void doStuff (const Container & c) {for (Container :: iterator i = c.begin(); i! = c.end(); ++ i) {...}}' Шаблон например, это не волнует, какой тип контейнера вы используете, если он предоставляет «итератор», «начало» и «конец». – 0x5453

+0

@ 0x5453 Я не понимаю, что вы говорите? Очевидно, контейнер должен возвращать итераторы. Я просто не думал, что возвращение исходных указателей было разумным. Вы обращаетесь к этому утверждению или что-то еще? –

+0

Сложная часть - это пространственные пространства, связанные с ADL: std :: vector :: iterator'. Указатели не имеют 'std' в качестве ассоциированного пространства имен. Стандарт не требует, чтобы итераторы имели 'std' как ассоциированное пространство имен. – MSalters

ответ

3

§ 24.2.1

Поскольку итераторы абстракция указателей, их семантика является обобщением наиболее семантики указателей в C++. Это гарантирует, что каждый шаблон функции, который принимает итераторы, работает также с обычными указателями .

Так что да, используя указатель, удовлетворяет всем требованиям для Random Access Iterator.

std::vector скорее предоставляет итераторы по нескольким причинам

  1. Стандарт говорит, что это должно быть.

  2. Было бы странным, если контейнеры, такие как std::map или std::set предоставленные итераторы в то время как std::vector только при условии, value_type* указатель. Итераторы обеспечивают согласованность в библиотеке контейнеров.

  3. Он позволяет специализации векторного типа, например, std::vector<bool>, где указатель value_type* не будет действительным итератором.

+0

Вы настраиваете «Стандарт говорит, что это должно» в заявлении «Итераторы - это абстракция указателей»? –

+0

«Стандарт говорит, что это должно» объясняет, почему существуют итераторы для векторов. Числа 2 и 3 - это всего лишь две возможные причины: почему * стандарт говорит, что это нужно. – lcs

2

Мои 50 центов:

итераторами являются общими способами доступа любого STL контейнера. То, что я чувствую, вы говорите: поскольку указатели в порядке, как замена итераторов для векторов, почему существуют итераторы для векторов?

Ну, кто сказал, что у вас не может быть дубликатов на C++? На самом деле хорошо иметь разные интерфейсы с одинаковой функциональностью. Это не должно быть проблемой.

С другой стороны, подумайте о библиотеках, которые имеют алгоритмы, которые используют итераторы. Если векторы не имеют итераторов, это просто приглашение к исключениям (исключения в лингвистическом, а не в смысле программирования). Каждый раз, когда приходится писать алгоритм, он должен делать что-то другое для векторов с указателями. Но почему? Нет причин для этой суеты. Просто совместите все так же.

+0

Какие операции вы должны иметь в виду, это должно быть сделано по-разному между итераторами и указателями? Я не могу думать ни о чем. –

+0

@JonathanMee Я считаю, что его точка зрения заключается в том, что итераторы просто позволяют вектору иметь одни и те же интерфейсы, поскольку другие классы - для предотвращения необходимости специального обращения с векторным классом, любым, кто предпочитает работать с итераторами над указателями на все остальное, для пример. – Carmageddon

+0

@Carmageddon Можете ли вы дать мне пример того, как вы будете работать по-другому с итератором, чем указатель? Это отличный ответ, если указатели должны обрабатываться по-разному или работать иначе, чем итераторы. Но если они предоставляют идентичные операторы и имеют одинаковое поведение, то это не отличный ответ. (Я использую указатели взаимозаменяемо с итераторами в течение многих лет.) –

2

Что эти комментарии говорят, что

template <typename T, ...> 
class vector 
{ 
public: 
    typedef T* iterator; 
    typedef const T* const_iterator; 
    ... 
private: 
    T* elems; // pointer to dynamic array 
    size_t count; 
    ... 
} 

является действительным. Аналогичным образом пользовательский контейнер, предназначенный для использования с алгоритмами std::, может это сделать. Затем, когда шаблон запрашивает Container::iterator тип, он возвращается в этом экземпляре равен T*, и это ведет себя правильно.

Соответственно, стандарт требует, чтобы у vector было определение для vector::iterator, и вы используете его в своем коде. На одной платформе он реализуется как указатель на массив, но на другой платформе это нечто другое. Важно то, что все это ведет себя одинаково во всех аспектах, которые специфицирует стандарт.

+0

Я считаю, что это единственный ответ, который затрагивает реальный вопрос, лежащий в основе ОП. – Angew