Russian Qt Forum
Ноябрь 23, 2024, 18:33 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: [РЕШЕНО] константная ссылка в foreach  (Прочитано 8606 раз)
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« : Январь 21, 2016, 14:58 »

мне нравится foreach красотой и компактностью, с другой стороны зачем он возвращает ссылку константу?
Код:
    QList<int> ls; ls<<1<<2<<3;
    foreach(const int &item, ls)
        *const_cast<int*>(&item) += 3; // или более жестоко *(int*)&item += 3;
    qDebug()<<ls;
Как то можно сделать подобный код красивее? Без const_cast
« Последнее редактирование: Январь 22, 2016, 12:49 от deMax » Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #1 : Январь 21, 2016, 15:01 »

c++11
Код
C++ (Qt)
for(int &item: ls){
   item += 3;
}
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #2 : Январь 21, 2016, 15:14 »

Спасибо.
А что скажете про C++11? стоит его включить для Qt5, проблем не возникнет?
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #3 : Январь 21, 2016, 15:16 »

У меня пока не возникало
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #4 : Январь 21, 2016, 15:20 »

использовать const_cast и модифицировать const данные - это UB, насколько я помню. Решение - использовать сишный "итератор" по индексам, или C++11, как написал __Heaven__
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #5 : Январь 21, 2016, 15:30 »

Итератор слишком громоздкая запись(для задачи пройтись по всем элементам он точно не нужен).
ub не будет, потому что ссылка не обязана быть константой, а foreach так требует, хотя это неверно.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #6 : Январь 21, 2016, 15:34 »

Ну вам в стандарте 0х всё-таки единственный путь - итераторы.
что такое ub?
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #7 : Январь 21, 2016, 15:37 »

ub - Undefined behavior(Неопределённое поведение). В данном случае все будет нормально, даже в бусте он не такой кривой:
Код:
QList<QString> a; BOOST_FOREACH(QString& s, a) s += "s";
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #8 : Январь 21, 2016, 15:39 »

Undefined behavior

Тьфу, блин. University at Buffalo

Так используйте тот, что в бусте. Ну или свой определите.
« Последнее редактирование: Январь 21, 2016, 15:46 от __Heaven__ » Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #9 : Январь 21, 2016, 15:50 »

так правильнее:
Код:
    QList<int> ls; ls<<1<<2<<3;
    foreach(const int &item, ls) {
        int &item2 = const_cast<int&>(item); // так, если много раз нужен
        item2 += 2;
        const_cast<int&>(item) += 3; } // или так

буст тяжеловат будет, проще const_cast использовать, может со временем в qt исправят эту ошибку.

p.s. с++11 хорош, надо будет как нибудь перейти.
Записан
__Heaven__
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2130



Просмотр профиля
« Ответ #10 : Январь 21, 2016, 15:54 »

deMax, уж лучше сделайте на итераторах. Точно наступите на грабли когда-нибудь с const_cast.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #11 : Январь 21, 2016, 17:36 »

так правильнее:
Код:
    QList<int> ls; ls<<1<<2<<3;
    foreach(const int &item, ls) {
        int &item2 = const_cast<int&>(item); // так, если много раз нужен
        item2 += 2;
        const_cast<int&>(item) += 3; } // или так
то есть это лучше, чем использовать индексы? ок.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
ssoft
Программист
*****
Offline Offline

Сообщений: 584


Просмотр профиля
« Ответ #12 : Январь 22, 2016, 08:37 »

Реализация foreach в Qt несколько криворукая и имеет описанные ограничения, часто уступает в производительности простому for через итераторы или индексы.
Вот в boost реализация оказалась отличной и без описанных ограничений. Но не тащить же еще и boost  Смеющийся

Такое кастование - это зло, которое нужно срочно искоренить из проекта!
К слову из-за того, что реализация QList implicit shared, таким кодом вы корректируете все взаимосвязанные с данным списком данные.

Если есть необходимость изменения данных в массиве QList, то необходимо использовать либо индексы, либо итераторы, либо C11, либо еще что-то, но никогда кастование!
Записан
deMax
Хакер
*****
Offline Offline

Сообщений: 600



Просмотр профиля
« Ответ #13 : Январь 22, 2016, 09:18 »

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

итераторы вещь хорошая, но когда идет последовательный перебор получается слишком много бестолкового кода в котором еще и опечататься можно, особенно если list какое нибудь длинное выражение)

>> К слову из-за того, что реализация QList implicit shared, таким кодом вы корректируете все взаимосвязанные с данным списком данные.
В моем случае будет нормально, хотя спасибо что предупредили. Наверно буду на с++11 переходить.

p.s. только что создал вектор и список на 1E7 элементов, заполнив единицами, int с=1 изначально
Код:
    foreach(const int &i, list1) { count*=i; }
Код:
    QVector<int>::Iterator it1;    for (it1 = list1.begin(); it1 != list1.end(); ++it1)        count*=*it1;

результат: для foreach (вектор 70мс список 200) итераторы (вектор 570 список 470) в режиме отладки
в режиме выпуска все примерно равны(добавил for из с++11):
vector (foreach 150 / for 150 / iterator 190) list (foreach  200 / for 150 / iterator 170) время в мс из QTime::elapsed()
« Последнее редактирование: Январь 22, 2016, 10:36 от deMax » Записан
Old
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4350



Просмотр профиля
« Ответ #14 : Январь 22, 2016, 09:22 »

Вы ограничены в выборе компилятора? Если нет, то используйте c++11. Для чего использовать конструкцию, которая пытается имитировть for, если есть сам for? Улыбающийся
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.424 секунд. Запросов: 23.