2016-04-29 2 views
2

Недавно я наткнулся на этот код в моем коде (упрощен здесь, конечно)Доступ к векторному итератору по индексу?

auto toDelete = std::make_shared<std::string>("FooBar"); 
std::vector<decltype(toDelete)> myVec{toDelete}; 
auto iter = std::find_if(std::begin(myVec), std::end(myVec), 
    [](const decltype(toDelete) _next) 
    { 
     return *_next == "FooBar"; 
    }); 

if (iter != std::end(myVec)) 
{ 
    std::shared_ptr<std::string> deletedString = iter[0]; 
    std::cout << *deletedString; 
    myVec.erase(iter); 
} 

Online Example

Теперь я заметил, что здесь мы имеем доступ итератор по индексации!

std::shared_ptr<std::string> deletedString = iter[0]; 

Я никогда не видел, чтобы кто доступ итератора по индексации раньше, так что я могу догадаться, что итератор получает лечение, как указатель, а затем получить доступ к первому элемент указал на указателе. Таким образом, этот код фактически эквивалентен:

std::shared_ptr<std::string> deletedString = *iter; 

Или это Неопределенное поведение?

+2

'x [y]' (в данном случае) точно такой же, как '* (x + y)'. Добавление нуля к итератору не меняет его. Поэтому 'iter [0]' совпадает с '* iter'. –

ответ

5

С cppreference documentation для RandomAccessIterator:

Expression: i[n]

семантика: *(i+n)

Поскольку итераторы std::vector «s отвечают требованиям RandomAccessIterator, их индексации эквивалентно добавление и разыменование, как обычный указатель. iter[0] эквивалентен *(iter+0), или *iter.

4

Это Standard соответствующее поведение

24.2.7 итераторы с произвольным доступом [random.access.iterators]

1 Класс или указатель типа Х удовлетворяет требованиям итератора произвольного доступа если в дополнение к удовлетворению требований для двунаправленных итераторов , следующие выражения действительны, как показано в таблице 118.

конвертируемые в качестве ссылки: *(a + n)

Обратите внимание, что это не требуется, чтобы конкретный итератор реализован как указатель. Любой класс итератора с перегруженным operator[], operator* и operator+ с указанной семантикой будет работать. Для std::vector категория итератора - это итератор с произвольным доступом, и ему требуется .

Смежные вопросы