Затем разыменуйте итератор. оператор против. -› оператор

Мне дали некоторый код 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();

Затем код получает доступ к x и y из the_iter следующим образом:

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

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

the_iter->x;
the_iter->y;

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


person Hosack    schedule 22.04.2015    source источник
comment
Может быть, они не знали об этом? Как вы говорите, они делают то же самое.   -  person DAhrens    schedule 23.04.2015
comment
Да, все в порядке. Спросите своего коллегу.   -  person juanchopanza    schedule 23.04.2015


Ответы (4)


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

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

person lisyarus    schedule 22.04.2015

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

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

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

person Scott M    schedule 22.04.2015
comment
Спасибо! Я не рассматривал возможность изучения перегрузки операторов. - person Hosack; 23.04.2015

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

person Austinh100    schedule 22.04.2015

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

В то время как 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
person Maxim Egorushkin    schedule 22.04.2015
comment
Верно, но оператор * может быть перегружен, а в случае с итератором STL при любом разыменовании используется перегрузка оператора. - person Dan Korn; 23.04.2015
comment
@DanKorn operator* не применяется рекурсивно к возвращаемому значению, в отличие от operator->. - person Maxim Egorushkin; 23.04.2015