Бред с итераторами

Тема в разделе "LANGS.C", создана пользователем systemio, 7 апр 2008.

  1. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    То что я только что узнал не описано ни в одной книге - даже для профи.
    простейший код:

    void main(void)
    {
    std::list<int> l;
    std::list<int>::iterator i = l.begin();
    std::list<int>::const_iterator ci = l.begin(); // !!!
    }

    не поверите но const_iterator begin() const { ... } никогда не вызывается!!! более того он не вызывается даже если этот код написать в констактном методе. более того для VS2003 этот код будет компилироваться только потому что в их библиотеке стл есть наследование простого итератора от константного - т.е. если сделать аналогию своих итераторов но убрать наследование, то нифига не откомпилируется.

    Вопрос: кто нить из мэтров С++ это описывал подробно!?
     
  2. KeSqueer

    KeSqueer Сергей

    Публикаций:
    0
    Регистрация:
    19 июл 2007
    Сообщения:
    1.183
    Адрес:
    Москва
    А что здесь подробно описывать? Код двух функций одинаков, зачем их две штуки делать?
    Код (Text):
    1.     iterator begin()
    2.         {   // return iterator for beginning of mutable sequence
    3.         return (iterator(_Nextnode(_Myhead), this));
    4.         }
    5.  
    6.     const_iterator begin() const
    7.         {   // return iterator for beginning of nonmutable sequence
    8.         return (const_iterator(_Nextnode(_Myhead), this));
    9.         }
    По аналогии:
    Код (Text):
    1. int gint;
    2.  
    3. const int * pint1 (void) {return &gint;}
    4.  
    5. int * pint2 (void) {return &gint;}
    6.  
    7. int _tmain(int argc, _TCHAR* argv[])
    8. {
    9.     pint1 ();
    10.     pint2 ();
    11. }
    два раза будет вызвана pint2, даже если ее тип поставить void *
     
  3. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    KeSqueer
    В целях оптимизации. Могут быть различия как в реализации итераторов, так и возвращении последних.

    Другое дело, что в С++ нет перегрузки функций по типу возвращаемого значения и лично мне не было ясно, как должны различаться вышеприведённые варианты методов.
     
  4. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Они различаются по наличию ключевого слова const после декларации. И выбор между методами делается по простому принципу: если объект, к которому применяется метод, описан как const, то вызывается второй метод, в противном случае - первый. Соответственно в примере systemio оба раза вызывается первый метод, поскольку объект не const. При втором вызове результат автоматически преобразуется к const_iterator - преобразование в эту сторону разрешено, но не наоборот (в <list> описание всего этого после опускания деталей имеет общий вид "class iterator : public const_iterator").

    Upd: чтобы вызвать таки const-метод, нужно сделать следующее:
    Код (Text):
    1. void func(const std::list<int> l)
    2. {
    3.   std::list<int>::const_iterator it = l.begin(); // <- здесь вызывается const-метод - если заменить слева const_iterator на
    4.                                                             // iterator, получим ошибку компиляции
    5. }
    6. int main()
    7. {
    8.   std::list<int> l;
    9.   std::list<int>::iterator it = l.begin(); // <- здесь вызывается не const-метод
    10.   func(l);
    11. }
     
  5. RedLord

    RedLord Member

    Публикаций:
    0
    Регистрация:
    23 июн 2005
    Сообщения:
    183
    Адрес:
    Ukraine
    при перегрузке, для мемберных функций учитывается "неявный аргумент" имеющий тип объекта
    по простому:
    begin можно заменить на:

    iterator begin(std::list<int>&);
    const_iterator begin(const std::list<int>&); // const версия

    а вызов на:
    std::list<int> l;
    std::list<int>::iterator it = begin(l);

    P.S. естественно это псевдокод, но по сути - так и происходит
     
  6. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    RedLord
    Понятно, спасибо.
     
  7. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    начинаю догонять хитрость всего этого. спасибо за ответы!!!
     
  8. systemio

    systemio New Member

    Публикаций:
    0
    Регистрация:
    18 мар 2008
    Сообщения:
    98
    еще не совсем понятно для реализации из борланда. там наследования нет - какже идет тогда приведение типа?

    template<class _Tp, class _Traits> struct _List_iterator : public _List_iterator_base { ... };

    template <class _Tp, class _Alloc> class list : public _List_base<_Tp, _Alloc>
    {
    typedef _List_iterator<_Tp, _Nonconst_traits<_Tp> > iterator;
    typedef _List_iterator<_Tp, _Const_traits<_Tp> > const_iterator;
    };