Оценка (де) справочных операторов

У меня есть (без комментариев) исходный файл, который я пытаюсь понять.

static const Map *gCurMap;
static std::vector<Map> mapVec;

затем

auto e = mapVec.end();
auto i = mapVec.begin();
while(i!=e) {
// ...
const Map *map = gCurMap = &(*(i++));
// ...
}

Я не понимаю что &(*(i++)) делает. Не компилируется при использовании i++, но для меня это выглядит так же, потому что я «увеличиваю» i, то я запрашиваю значение по данному адресу, а затем я запрашиваю адрес этого значения ?!

3

Решение

Не за что. &*x такой же как operator&(operator*(x)), который может быть чем угодно.

Это верно только для типы указателей лайк T * p тот &*p такой же как p, Но C ++ имеет пользовательские типы и перегружаемые операторы.

Оператор разыменования (*) обычно перегружается для итераторов, чтобы они возвращали ссылку на элемент контейнера. Эффект оператора амперсанда (&) на элементе контейнера лежит автор класса; если вы хотите взять адрес безоговорочно, вы должны использовать std::addressof(*i++) (из вашего любимого заголовка<memory>).

4

Другие решения

mapVec.begin() возвращает итератор с перегруженным operator++, «Разыменование» (перегружено operator*) итератора, чтобы добраться до map объект. Ссылка & хорошо, потому что map является указателем, поэтому он присваивается адресу объекта из разыменования i, Мы не можем просто i++ потому что это все равно будет итератор, а не фактический map объект.

3

i итератор, *i является объектом, на который указывает этот итератор, и &*i это адрес этого объекта. Если бы итератор был просто старым указателем, это было бы ненужным, но обычно это не так просто. Итератор часто имеет некоторый тип класса, который перегружает operator* чтобы позволить вам получить доступ к объекту, на который он указывает. Так что это в основном преобразование из итератора в элемент в указатель на этот элемент.

Я бы переместил приращение на следующую строку, потому что это только затрудняет понимание данной строки. Это было бы эквивалентно, потому что значение i++ просто i и приращение происходит потом.

2

Это не то же самое: i это итератор. Разыменование итератора дает ссылку на некоторый объект, т.е. T& для какого-то типа T, Взятие адреса такого объекта дает T*адрес объекта в месте нахождения i, То, что итератор также увеличивается в том же выражении, является просто деталью и, вероятно, является плохой идеей (постинкремент обычно менее эффективен, чем предварительный инкремент, и нет реальной необходимости постинкрементно увеличивать итератор в отрывке кода: он также может быть предварительно увеличенным в каком-то другом месте).

2
По вопросам рекламы [email protected]