Отмена ссылки на итератор затем «.» оператор против. & Quot; — & GT; & Quot; оператор

Мне дали код C ++, который имеет список / итератор следующей структуры.

typedef struct{
int x;
int y;
}my_struct;

std::list<my_struct> the_list;
std::list<my_struct>::iterator the_iter = the_list.begin();

Затем код обращается к х и у the_iter сюда:

(*the_iter).x;
(*the_iter).y;

Я хочу изменить их на более читаемую версию:

the_iter->x;
the_iter->y;

С моей точки зрения C, это совершенно нормально для разыменования указателей. Это также касается итераторов? Есть ли причина, по которой мой коллега использовал бы (*pointer). вместо p->

2

Решение

Рассматривая общий случай, может случиться так, что некоторый класс итератора не обеспечит operator ->и делает (*it).x будет единственным возможным способом. Другая возможность заключается в том, что operator * а также operator -> имеют некоторую нестандартную семантику и не являются взаимозаменяемыми. Однако этот класс не сможет удовлетворить какую-либо концепцию итератора и, технически, не будет итератором.

В вашем случае это std::list<T>::iterator, для которого it->x а также (*it).x эквивалентны.

6

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

Этот ответ имеет представление о том, почему оба метода существуют для указателей, если они достигают одного и того же: https://stackoverflow.com/a/6632474/3113508

Ваше изменение было бы совершенно нормально (и, вероятно, большинством) для итераторов STL по той же причине -> Оператор, как правило, предпочтительнее для использования с указателями.

Тем не менее, имейте в виду, что унарный * оператор и ->Оператор может быть перегружен для обеспечения семантически различного поведения в пользовательских классах. Таким образом, потенциально кто-то может выбрать для использования * или же -> по-другому, так что foo->bar больше не совпадает с (*foo).bar, Убедитесь, что вы знакомы с документацией для используемых вами классов.

5

Нет, стилевые предпочтения / знание -> будет единственной причиной, по которой они будут использовать (* a). против ->,

2

Разница в том, что operator-> может быть перегружен для возврата нескольких уровней прокси-объектов с перегруженными operator-> к которому он затем снова применяется рекурсивно, пока не будет возвращен простой указатель, как в Обертывание вызовов функций-членов C ++ от Bjarne Stroustrup.

В то время как operator. не может быть перегружен в C ++.

Пример из этой статьи:

#include<iostream>

using namespace std;

void prefix() { cout<< "prefix"; }
void suffix() { cout<< " suffix\n"; }

template<class T>
class Call_proxy{
T* p;
public:
Call_proxy(T* pp) :p(pp){ }
˜Call_proxy() { suffix() ; }
T* operator->() { return p; }
};

template<class T>
class Wrap{
T* p;
public:
Wrap(T* pp) :p(pp) { }
Call_proxy<T> operator->() { prefix() ; return Call_proxy<T>(p) ; }
};

class X{ // one user class
public:
X() { cout<< "make an X\n"; }
int f() const{ cout<< "f()"; return 1; }
void g() const{ cout<< "g()"; }
};

class Y{ // another user class
public:
Y() { cout<< "make a Y\n"; }
void h() const{ cout<< "h()"; }
};

int main() // simple test code
{
Wrap<X> xx(new X) ;
Wrap<Y> yy(new Y) ;
if(xx->f()) cout<< "done\n";
xx->g() ;
yy->h() ;
return 0;
}

Каждый звонок xx а также yy заключен в скобки парой вызовов prefix () / suffix (), поэтому программа создала:

make an X
make a Y
prefix f() suffix
done
prefix g() suffix
prefix h() suffix
1
По вопросам рекламы [email protected]