Russian Qt Forum

Qt => Вопросы новичков => Тема начата: fisenkdima от Ноябрь 18, 2013, 15:12



Название: Константный итератор вместо обычного. Чистый С++
Отправлено: fisenkdima от Ноябрь 18, 2013, 15:12
На код ниже компилятор выдаёт ошибку:
Код:
std::list<std::pair<unsigned int, int> > headIndexes;
headIndexes.push_back( std::make_pair( 0, -1 ) );
std::list<std::pair<unsigned int, int> >::iterator iter = headIndexes.end();
--iter;

ошибка: conversion from 'std::list<std::pair<unsigned int, int> >::const_iterator {aka std::_List_const_iterator<std::pair<unsigned int, int> >}'
to non-scalar type 'std::list<std::pair<unsigned int, int> >::iterator {aka std::_List_iterator<std::pair<unsigned int, int> >}' requested
std::list<std::pair<unsigned int, int> >::iterator iter = headIndexes.end();
                                                                                                ^
Я понимаю, что std::list::end() возвращает константный итератор, и что я не могу присваивать его обычному итератору.

Как заставить этот метод вернуть обычный итератор? Метод ведь перегруженный, и существует нужная мне версия.

mingw 4.8, QTCreator, QT 5.1.1.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: alex312 от Ноябрь 18, 2013, 16:44
нужно больше подробностей, у меня код нормально компилируется.
Код
C++ (Qt)
   class test
   {
   public:
       void test_1() const
       {
           std::list<std::pair<unsigned int, int> > headIndexes;
           headIndexes.push_back( std::make_pair( 0, -1 ) );
           std::list<std::pair<unsigned int, int> >::iterator iter = headIndexes.end();
           --iter;
       }
   };
 
   test t;
   t.test_1();


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: fisenkdima от Ноябрь 18, 2013, 16:53
Больше подробностей... Это можно.

https://github.com/Dalidul/FSAT/blob/lazy/headtailliteral.h
https://github.com/Dalidul/FSAT/blob/lazy/headtailliteral.cpp

в файле .срр строчки 67 и 81.

А на основании чего делается выбор между перегруженными версиями метода? Не из типа переменной, в которую мы хотим сохранить результат?


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Old от Ноябрь 18, 2013, 16:59
Дело происходит в константном методе, поэтому все константное.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: mutineer от Ноябрь 18, 2013, 17:03
Дело происходит в константном методе, поэтому все константное.

Как все? Даже локальные переменные? Странно...


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Old от Ноябрь 18, 2013, 17:05
Как все? Даже локальные переменные? Странно...
Почему локальные? Итератор конструируется для члена класса.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: alex312 от Ноябрь 18, 2013, 17:07
Дело происходит в константном методе, поэтому все константное.
А  как же мой тестовый код?


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: fisenkdima от Ноябрь 18, 2013, 17:07
Дело происходит в константном методе, поэтому все константное.

Истину говорите, сенсей.
Спасибо. Я бы не догадался.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: fisenkdima от Ноябрь 18, 2013, 17:08
Дело происходит в константном методе, поэтому все константное.
А  как же мой тестовый код?

В тестовом коде переменная, которая создает итератор - локальная.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: mutineer от Ноябрь 18, 2013, 17:14
Как все? Даже локальные переменные? Странно...
Почему локальные? Итератор конструируется для члена класса.


А, строчкой выше создается другой лист, точно


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Old от Ноябрь 18, 2013, 17:18
Указатель на список delta лучше сразу делать умным, а не при выходе из метода.
Что-бы сразу исключить любые утечки памяти.


Название: Re: Константный итератор вместо обычного. Чи&
Отправлено: fisenkdima от Ноябрь 18, 2013, 17:24
Указатель на список delta лучше сразу делать умным, а не при выходе из метода.
Что-бы сразу исключить любые утечки памяти.

Принято. Вот только намного ли замедлится операция разыменования, при учёте, что мы будем делать её ооочень много раз (я имею ввиду не конкретно в данном методе, а вообще, если вдруг будет стоять выбор между умным и обычным указателем в критично важном для быстродействия блоке кода)?

Я ещё не вполне разобрался с тем, как правильно (а вернее, когда правильно) ловить исключения, которые могут возникнуть при нехватке кучи.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Old от Ноябрь 18, 2013, 17:28
Тут не только в исключениях дело, вы можете добавить в дальнейшем выход из метода, где то по середине и забыть удалять этот список руками. А умный указатель будет это делать сам.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: fisenkdima от Ноябрь 18, 2013, 17:29
Тут не только в исключениях дело, вы можете добавить в дальнейшем выход из метода, где то по середине и забыть удалять этот список руками. А умный указатель будет это делать сам.

Да, это я понял.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Old от Ноябрь 18, 2013, 17:40
А вы напишите маленький тест и все увидите сами. :)
Ничтожное (хотя я сомневаюсь что вы его заметите) снижение производительности на разименование никак не может сравниться с удобством и эффективностью умных указателей.
Ну тесты и профилировщик это все скажет и без меня. :)


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: fisenkdima от Ноябрь 18, 2013, 17:44
А вы напишите маленький тест и все увидите сами. :)
Ничтожное (хотя я сомневаюсь что вы его заметите) снижение производительности на разименование никак не может сравниться с удобством и эффективностью умных указателей.
Ну тесты и профилировщик это все скажет и без меня. :)

Принято)


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Igors от Ноябрь 18, 2013, 19:05
Почему не просто back() ?


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: fisenkdima от Ноябрь 19, 2013, 03:18
Почему не просто back() ?
Потому что потом я делаю перебор элементов контейнера. И их может быть больше, чем один.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Igors от Ноябрь 19, 2013, 09:50
Потому что потом я делаю перебор элементов контейнера. И их может быть больше, чем один.
Если Вы хотели перебирать в обратном порядке - есть штатный rbegin()


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: fisenkdima от Ноябрь 19, 2013, 09:51
Потому что потом я делаю перебор элементов контейнера. И их может быть больше, чем один.
Если Вы хотели перебирать в обратном порядке - есть штатный rbegin()

А вот об этом я не знал. Спасибо. Это как раз то, что нужно.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Igors от Ноябрь 19, 2013, 10:02
Глянул Ваши исходники - ну конечно сходу во все подробности не вник, так все аккуратно, но "сопля длинная", может лучше так
Код
C++ (Qt)
typedef std::shared_ptr<std::list<unsigned int> >  TSharedList;
И использовать TSharedList. А то читается тяжеловато


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Old от Ноябрь 19, 2013, 10:09
может лучше так
Лучше начиная от pair и далее все нормально назвать. :)

Код
C++ (Qt)
typedef std::shared_ptr<std::list<unsigned int> >  TSharedList;
Не стоит акцентировать внимание на shared, в программе практически все указатели будут shared (ну и некоторые weak), а то что это указатель выделить нужно:
Код
C++ (Qt)
typedef std::list<unsigned int> DataList
typedef std::shared_ptr<DataList>  DataListPtr;
typedef std::shared_ptr<DataList>  datalist_ptr;
 


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: fisenkdima от Ноябрь 19, 2013, 12:39
Вариант Old-а, на мой взгляд, очень хорош. Сократить название типа + скрыть ненужные подробности. Круто.

Я как-то до сих пор не догадывался повышать читабельность кода таким образом. Приму на заметку.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Bepec от Ноябрь 19, 2013, 13:36
Самое главное при таком подходе не уйти в крайность. Когда начнут появляться дефайны дефайнов дефайнов.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Old от Ноябрь 19, 2013, 13:45
Самое главное при таком подходе не уйти в крайность. Когда начнут появляться дефайны дефайнов дефайнов.
Какие дефайны? Не надо дефайнов. :)
А вот typedef'ов побольше.


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: gil9red от Ноябрь 19, 2013, 13:55
Самое главное при таком подходе не уйти в крайность. Когда начнут появляться дефайны дефайнов дефайнов.
Может тайпдефы тайпдефов тайпдефов? :)


Название: Re: Константный итератор вместо обычного. Чистый С++
Отправлено: Пантер от Ноябрь 19, 2013, 14:06
А еще можно using в новом стандарте. :)