Russian Qt Forum

Qt => Вопросы новичков => Тема начата: deMax от Январь 21, 2016, 14:58



Название: [РЕШЕНО] константная ссылка в foreach
Отправлено: deMax от Январь 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


Название: Re: константная ссылка в foreach
Отправлено: __Heaven__ от Январь 21, 2016, 15:01
c++11
Код
C++ (Qt)
for(int &item: ls){
   item += 3;
}


Название: Re: константная ссылка в foreach
Отправлено: deMax от Январь 21, 2016, 15:14
Спасибо.
А что скажете про C++11? стоит его включить для Qt5, проблем не возникнет?


Название: Re: константная ссылка в foreach
Отправлено: __Heaven__ от Январь 21, 2016, 15:16
У меня пока не возникало


Название: Re: константная ссылка в foreach
Отправлено: Alex Custov от Январь 21, 2016, 15:20
использовать const_cast и модифицировать const данные - это UB, насколько я помню. Решение - использовать сишный "итератор" по индексам, или C++11, как написал __Heaven__


Название: Re: константная ссылка в foreach
Отправлено: deMax от Январь 21, 2016, 15:30
Итератор слишком громоздкая запись(для задачи пройтись по всем элементам он точно не нужен).
ub не будет, потому что ссылка не обязана быть константой, а foreach так требует, хотя это неверно.


Название: Re: константная ссылка в foreach
Отправлено: __Heaven__ от Январь 21, 2016, 15:34
Ну вам в стандарте 0х всё-таки единственный путь - итераторы.
что такое ub?


Название: Re: константная ссылка в foreach
Отправлено: deMax от Январь 21, 2016, 15:37
ub - Undefined behavior(Неопределённое поведение). В данном случае все будет нормально, даже в бусте он не такой кривой:
Код:
QList<QString> a; BOOST_FOREACH(QString& s, a) s += "s";


Название: Re: константная ссылка в foreach
Отправлено: __Heaven__ от Январь 21, 2016, 15:39
Undefined behavior

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

Так используйте тот, что в бусте. Ну или свой определите.


Название: Re: константная ссылка в foreach
Отправлено: deMax от Январь 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 хорош, надо будет как нибудь перейти.


Название: Re: константная ссылка в foreach
Отправлено: __Heaven__ от Январь 21, 2016, 15:54
deMax, уж лучше сделайте на итераторах. Точно наступите на грабли когда-нибудь с const_cast.


Название: Re: константная ссылка в foreach
Отправлено: kambala от Январь 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; } // или так
то есть это лучше, чем использовать индексы? ок.


Название: Re: константная ссылка в foreach
Отправлено: ssoft от Январь 22, 2016, 08:37
Реализация foreach в Qt несколько криворукая и имеет описанные ограничения, часто уступает в производительности простому for через итераторы или индексы.
Вот в boost реализация оказалась отличной и без описанных ограничений. Но не тащить же еще и boost  ;D

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

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


Название: Re: константная ссылка в foreach
Отправлено: deMax от Январь 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()


Название: Re: константная ссылка в foreach
Отправлено: Old от Январь 22, 2016, 09:22
Вы ограничены в выборе компилятора? Если нет, то используйте c++11. Для чего использовать конструкцию, которая пытается имитировть for, если есть сам for? :)


Название: Re: константная ссылка в foreach
Отправлено: Igors от Январь 22, 2016, 10:42
К слову из-за того, что реализация QList implicit shared, таким кодом вы корректируете все взаимосвязанные с данным списком данные.
Почему?
Код
C++ (Qt)
QVector <int> vec;
vec << 1 << 2 << 3;
QVector second = vec;  // пока vec и second шарят одну копию данных
int & a = const_cast<int &> (vec[0]);
 
Да, const_cast, но ведь все равно выполняется оператор [], он возвращает неконстантную ссылку, значит расшарит данные

Edit: A! Так foreach использует константный итератор - тогда да, никакого расшаривания не будет. Так это ж hidden feature!  :)


Название: Re: константная ссылка в foreach
Отправлено: deMax от Январь 22, 2016, 11:11
Вот это штука "implicit shared" сильно на производительности сказывается или как? Можно ее отключить?
А что у нас есть вместо QVector/Qlist... только std::vector?

Как перед foreach расшарить данные, чтобы были в единственном экземпляре?
Сделали бы в Qt не константный foreach который бы и расшаривал.


Название: Re: константная ссылка в foreach
Отправлено: Igors от Январь 22, 2016, 11:27
Вот это штука "implicit shared" сильно на производительности сказывается или как? Можно ее отключить?
А что у нас есть вместо QVector/Qlist... только std::vector?

Как перед foreach расшарить данные, чтобы были в единственном экземпляре?
Сделали бы в Qt не константный foreach который бы и расшаривал.
Любой вызов неконстантного метода (напр ls[0]) вызовет расшаривание. По поводу форыча
Код
C++ (Qt)
for (int i = 0; i < lst.size(); ++i) {
 int & a = lst[i];
 ...
}
Чего не хватат? Чего неймется, к чему поиск "более элегантных" решений, обычный рез-т которых = 1 строка вместо 2, зато капитально заморочить яйца читающему код? Ей-богу, фигней занимаетесь  :'(


Название: Re: константная ссылка в foreach
Отправлено: ssoft от Январь 22, 2016, 12:04
Если вы используете такой вариант

Код
C++ (Qt)
void ( const QList< int > & values )
{
   ...
   foreach ( const int & value, values )
   {
       const_cast< int & >( value ) = 1;
   }
   ...
}
 

то values не вызывает проверку того, что он shared. Данные будут изменены в обобщенном списке.

Для выполнения detach() необходимо вызвать любой не константный метод values.

И ... "implicit shared" сильно на производительности сказывается, так как не выполняются лишние копирования данных списка.


Название: Re: константная ссылка в foreach
Отправлено: deMax от Январь 22, 2016, 12:49
>>Чего не хватат? Чего неймется
у Вас lst 2 раза используется, если это будет функция класса(peoples.getMen(Vasia Pupkin).getHand.getFingers()) получим копипаст или дополнительную строчку
Да я только что узнал про эту "великую фичу"(думал такая ерунда только в QSharedPointer), сижу в шоке - мне она как собаке пятое колесо :(
Вещь в принципе неплохая, и на производительности современных ПК не скажется, скорее даже лучше станет - т.к. код можно писать более грязно(в стиле си шарпа).

p.s. всем спасибо, буду переходить на C++11.


Название: Re: константная ссылка в foreach
Отправлено: deMax от Январь 22, 2016, 14:02
>>Чего не хватат? Чего неймется
у Вас lst 2 раза используется, если это будет функция класса(peoples.getMen(Vasia Pupkin).getHand.getFingers()) получим копипаст или дополнительную строчку
Да я только что узнал про эту "великую фичу"(думал такая ерунда только в QSharedPointer), сижу в шоке - мне она как собаке пятое колесо :(
Вещь в принципе неплохая, и на производительности современных ПК не скажется, скорее даже лучше станет - т.к. код можно писать более грязно(в стиле си шарпа).
Хотя частичная вина этой штуки тоже есть, что Qt такой тормознутый и жирный.

p.s. всем спасибо, буду переходить на C++11.