Re[8]: Есть ли жизнь после перемещения?
От: Videoman Россия https://hts.tv/
Дата: 20.11.18 21:23
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Во-первых, не все быстрые типы хорошо поддаются move.

E>Скажем, если у нас строчки устроены так, что короткие строки лежат в буфере прямо "на борту" объекта, то их перемещение будет так же дорого, как копирование.
E>При этом у RVO/NRVO такой проблемы нет.

Вы противопоставляете RVO/NRVO move-семантике, как-будто она перестает работать.

E>Я бы предпочёл какие-то средства явно управлять RVO/NRVO, например...


Зачем управлять тем, чем компилятор и так управляет оптимально:
— сначала пробует RVO/NRVO
— затем move
— затем копия

E>Так это была история про то, что move-семантика умеет расползаться...

E>И, кстати, в рассказанной истории я не совсем понял, в каком месте были такие уж супер-кривые руки?

Просто методом простейших логических заключений: если заменить ваш move-конструктор copy-конструктором, то гарантировано все будет работать — значит ошибка у вас в реализации move-конструктора.

E>Ну было бы круто, например, уметь как-то потребовать, что бы RVO\NRVO точно сработало...


Зачем усложнять там, где автоматика и так идеально работает?

E>В общем резюме такое:


У меня создается ощущение, что вы критикует move-семантику до конца с ней не разобравшись. Вы не обязаны ее использовать в старом коде, все работает также как и раньше, но во многих случаях она начинает работать автоматом, за вас, сама.
Re[8]: Есть ли жизнь после перемещения?
От: Videoman Россия https://hts.tv/
Дата: 20.11.18 21:32
Оценка:
Здравствуйте, Erop, Вы писали:

E>Почему неправильно?

Я же не телепат

E>А в move-конструкторе-то что писать?

Не нужно переопределять move-конструктор пока вы не поймете как вся эта механика работает, и я вам гарантирую, что ничего не сломается, а вот оптимизация при работе с STL уже будет.

E>Почему бы его не выражать просто методом move?

Во многих случаях хочется синтаксис проще. Потом, как выразить forward reference? Как быть в случае если не получилось RVO?
Re[9]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 20.11.18 21:48
Оценка:
Здравствуйте, Videoman, Вы писали:

E>>При этом у RVO/NRVO такой проблемы нет.

V>Вы противопоставляете RVO/NRVO move-семантике, как-будто она перестает работать.

Моя логика состоит в том, что ту версию move-семантики ввели так, как ввели, ради нескольких конкретных сценариев.
И я их обсуждаю...

E>>Я бы предпочёл какие-то средства явно управлять RVO/NRVO, например...


V>Зачем управлять тем, чем компилятор и так управляет оптимально:

V>- сначала пробует RVO/NRVO

Например было бы круто как-то сказать компилятору, что в этом месте надо обломаться, если не получилось.
И в этом случае, кстати, можно было бы не требовать наличие открытого конструктора копии

V>- затем move

V>- затем копия

Ну если всё равно копию возвращать, то всё понятно, а число случаев, когда понадобится move в этом сценарии будет довольно маленьким...

E>>И, кстати, в рассказанной истории я не совсем понял, в каком месте были такие уж супер-кривые руки?


V>Просто методом простейших логических заключений: если заменить ваш move-конструктор copy-конструктором, то гарантировано все будет работать — значит ошибка у вас в реализации move-конструктора.


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

E>>Ну было бы круто, например, уметь как-то потребовать, что бы RVO\NRVO точно сработало...

V>Зачем усложнять там, где автоматика и так идеально работает?
Если она так идеально работает, то почему бы не сделать её работу обязательной и контролируемой?


V>У меня создается ощущение, что вы критикует move-семантику до конца с ней не разобравшись.

Там не с чем особо разбираться. Там проблемы не в том, что концепция сложная, а в том, что не совсем последовательная...
Например, смотри на стартовое сообщение темы

V>Вы не обязаны ее использовать в старом коде, все работает также как и раньше,

К сожалению не бывает старого кода, с которым работают программисты, и который совсем не меняют. А если меняют, обновляют библиотеки и т. д, то и move-семантика приходит к вам, совсем и не обязательно потому, что вам это надо.
Результат получился смешной -- ради оптимизации некоторых редких случаев передачи параметров/результатов функций и потому, что у std::vector кривой дизайн ещё и в месте перемещения элементов и самих векторов, ввели средство, которое неконтролируемо расползается по коду. Большое спасибо.

V>но во многих случаях она начинает работать автоматом, за вас, сама.


Грубо говоря в этом-то и состоит главная проблема
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 20.11.18 22:02
Оценка:
Здравствуйте, Videoman, Вы писали:

E>>Почему неправильно?

V>Я же не телепат
Ну то, что неправильно, утверждаешь, почему-то…


E>>А в move-конструкторе-то что писать?

V>Не нужно переопределять move-конструктор пока вы не поймете как вся эта механика работает, и я вам гарантирую, что ничего не сломается, а вот оптимизация при работе с STL уже будет.
Откуда возникнет оптимизация, если не будет move-конструкторов?

E>>Почему бы его не выражать просто методом move?

V>Во многих случаях хочется синтаксис проще.
Ну метод move вместо присваивания, которое не всегда очевидно в этом месте copy или move, разве это сложнее синтаксис? Наоборот понятнее что код делает...

V>Потом, как выразить forward reference?

Зачем? Какие сценарии хочется поддержать?

V>Как быть в случае если не получилось RVO?


Что значит "не получилось"?


RVO/NRVO, по сути, это просто неявная передача в функцию адреса буфера, в котором надо создать результат + такая модификация кода функции компилятором, что бы результат создавался по этому адресу.

Просто представь, например, что была бы какая-то конструкция, скажем auto return, которая требовала бы возврат результата по такому механизму (и не требовала бы наличия конструктора копии, если нет явного его вызова)
В каких случаях этого бы не хватило?
Очевидно, если бы мы должны были копировать/перемещать результат откуда-то ещё, кроме автоматической переменной. Например из поля какого-то объекта.
Но тогда нам надо было бы
1) Иметь для этого данного методы move или функцию swap
2) Уметь создавать "пустой" объект

Ну так и нынешняя move-семантика требуют умения создавать/оставлять "пустой" объект, и, при этом написать конструктор и присваивание.
Ну и чем это лучше, кроме того, что RVO на самом деле бесплатная штука, а move-семантика, только почти бесплатная, да ещё и неконтролируемо расползаться умеет



Я не про то, что введя в C++ move-семантику, решили несуществующие проблемы. Я про то, что мне не нравится то, как их решили. Можно было решить значительно менее неявно и менее агрессивно меняя язык...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 22:15
Оценка:
Здравствуйте, Erop, Вы писали:

E>>>Почему бы его не выражать просто методом move?

V>>Во многих случаях хочется синтаксис проще.
E>Ну метод move вместо присваивания, которое не всегда очевидно в этом месте copy или move, разве это сложнее синтаксис? Наоборот понятнее что код делает...

При помощи move метода нельзя сконструировать новый объект, как при помощи move конструктора.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[11]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 20.11.18 22:17
Оценка:
Здравствуйте, rg45, Вы писали:


R>При помощи move метода нельзя сконструировать новый объект, как при помощи move конструктора.


1) Зачем его конструировать, если есть старый?
2) То, что нельзя написать такую функцию move, которая создаёт новый объект, это, IMHO, недостаток управления RVO...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[12]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 23:05
Оценка:
Здравствуйте, Erop, Вы писали:

R>>При помощи move метода нельзя сконструировать новый объект, как при помощи move конструктора.


E>1) Зачем его конструировать, если есть старый?


Есть старый и мы хотим создать новый, переместив в него содержимое из старого. И для этого нам придется объект сначала создать, в состоянии, которое никому не нужно, и только потом уже выполнить перемещение при помощи специального метода. Кустарщина какая-то. И как такой механизм использовать при тех же переаллокациях вектора? Мы имя этого медота резервируем, делаем еще одну специальную функцию?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[10]: Есть ли жизнь после перемещения?
От: Videoman Россия https://hts.tv/
Дата: 21.11.18 08:13
Оценка:
Здравствуйте, Erop, Вы писали:

E>Ну если всё равно копию возвращать, то всё понятно, а число случаев, когда понадобится move в этом сценарии будет довольно маленьким...


Согласен, но случаи все-таки есть.

E>Если применить не самые простейшие логические рассуждения, то станет ясно, что move-конструкторы самих базовых классов были корректные. Проблемы возникали в автоматически сгенерированных move-конструкторах классов-наследников...


Но это не специфика move-конструктора. C copy-конструктором все тоже самое. В С++ нужно смотреть подходит ли вам дефолтная реализация. Просто возьмите за правило: если вам не подходит дефолтный copy-
конструктор, и move-конструктор не подойдет, его нужно переопределить. Но это все только в том случае, если вы решите осознанно использовать move. Если вы его явно не определите, тое компилятор сам запретит его использование, за вас и старый код не поломается.

E>Если она так идеально работает, то почему бы не сделать её работу обязательной и контролируемой?


В С++ и так много чего нужно контролировать, зачем вам еще одна головная боль там, где и так все хорошо .

E>Там не с чем особо разбираться. Там проблемы не в том, что концепция сложная, а в том, что не совсем последовательная...

E>Например, смотри на стартовое сообщение темы

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

E>К сожалению не бывает старого кода, с которым работают программисты, и который совсем не меняют. А если меняют, обновляют библиотеки и т. д, то и move-семантика приходит к вам, совсем и не обязательно потому, что вам это надо.


По умолчанию, сама она к вам не придет. Для этого, как минимум, нужно начать определять свои move-конструкторы. Я уже написал выше почему.
Re[10]: Есть ли жизнь после перемещения?
От: Videoman Россия https://hts.tv/
Дата: 21.11.18 08:44
Оценка:
Здравствуйте, Erop, Вы писали:

E>Откуда возникнет оптимизация, если не будет move-конструкторов?


Если контейнеру не нужно перемещать ваши объекты, то он будет сам mov-ваться при передачи и возврате по значению.

E>Ну метод move вместо присваивания, которое не всегда очевидно в этом месте copy или move, разве это сложнее синтаксис? Наоборот понятнее что код делает...


Если у вас старый код, то вам не нужно об этом думать, всегда будет копирование.

E>Зачем? Какие сценарии хочется поддержать?

Например, оптимальная передача параметров в функцию, не зависимо от того какой тип параметра передается.

E>Что значит "не получилось"?

Я не спец по компиляторам, но RVO/NRVO возможно не всегда. В этом случае следующим методом по очереди будет move.

E>RVO/NRVO, по сути, это просто неявная передача в функцию адреса буфера, в котором надо создать результат + такая модификация кода функции компилятором, что бы результат создавался по этому адресу.

Все верно.

E>Очевидно, если бы мы должны были копировать/перемещать результат откуда-то ещё, кроме автоматической переменной. Например из поля какого-то объекта.

E>Но тогда нам надо было бы
E>1) Иметь для этого данного методы move или функцию swap
E>2) Уметь создавать "пустой" объект

E>Ну так и нынешняя move-семантика требуют умения создавать/оставлять "пустой" объект, и, при этом написать конструктор и присваивание.

E>Ну и чем это лучше, кроме того, что RVO на самом деле бесплатная штука, а move-семантика, только почти бесплатная, да ещё и неконтролируемо расползаться умеет

E>

E>Я не про то, что введя в C++ move-семантику, решили несуществующие проблемы. Я про то, что мне не нравится то, как их решили. Можно было решить значительно менее неявно и менее агрессивно меняя язык...

Ну С++ не требует от вас использовать move, куда уж прозрачнее . Move нужен тех случаев, где он нужен и приносит выгоду, а также для явного выражения семантики объектов, которые принципиально не копируемые. Теперь, если нужно, это можно выразить явно и компилятор все будет проверять за вас.
Re[10]: Есть ли жизнь после перемещения?
От: B0FEE664  
Дата: 21.11.18 09:13
Оценка:
Здравствуйте, Erop, Вы писали:

V>>но во многих случаях она начинает работать автоматом, за вас, сама.

E>Грубо говоря в этом-то и состоит главная проблема
std::string  str1 = fun1();
std::string  str2 = fun2();
std::string  str3 = fun3();

std::string  strResult = str1 + str2 + str3 + fun4();  // какая здесь проблема?
И каждый день — без права на ошибку...
Re[8]: Есть ли жизнь после перемещения?
От: B0FEE664  
Дата: 21.11.18 09:19
Оценка:
Здравствуйте, Erop, Вы писали:

V>>Но вообще, с приходом move-семантики появилась возможность безопасно выражать в коде поведение объектов которые невозможно скопировать, но можно передать владение ими, например: thread, file, uniqe_ptr и т.д.

E>Почему бы его не выражать просто методом move?

Что должен возвращать метод move?
И каждый день — без права на ошибку...
Re[7]: Есть ли жизнь после перемещения?
От: B0FEE664  
Дата: 21.11.18 09:40
Оценка:
Здравствуйте, Erop, Вы писали:

BFE>>Скорее "да", чем "нет", но прошу учесть, что это мнение, а не знание.

E>Разве вставка не в конец в std::vector сейчас не через цепочку move-конструкторов/присваиваний работает?
Да, это так. Используется std::move_backward. Об этом я узнал только сейчас (или я забыл о том, что это знал), когда полез в исходники и посмотрел. В работе я этого не замечал, что, кстати, говорит в пользу move семантики.
И каждый день — без права на ошибку...
Re[8]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 21.11.18 09:58
Оценка: +1
Здравствуйте, B0FEE664, Вы писали:

BFE>Да, это так. Используется std::move_backward. Об этом я узнал только сейчас (или я забыл о том, что это знал), когда полез в исходники и посмотрел. В работе я этого не замечал, что, кстати, говорит в пользу move семантики.


Конечно, перемудрили они с этими мувами. Теперь в стандарной библиотеке присутствуют два совершенно разных мува: один в алгоритмах: https://en.cppreference.com/w/cpp/algorithm/move, другой — в утилитах: https://en.cppreference.com/w/cpp/utility/move. С одинаковм, именем, в одном и том же пространстве имен — оба std::move — но совершенно разной семантикой.

Я бы на их месте постарался для вот этого второго move подобрать какое-нибудь более подходящее название. Например, make_rvalue, или rvalue_cast. С учетом того, что на самом деле эта функция ничего никуда не перемещает. Что часто вводит в заблуждение тех, кто только начинает вникать в имплементацию мув семантики.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 21.11.2018 10:06 rg45 . Предыдущая версия .
Re[6]: Есть ли жизнь после перемещения?
От: ViTech  
Дата: 21.11.18 09:59
Оценка:
Здравствуйте, andyp, Вы писали:

A>Здравствуйте, ViTech, Вы писали:


VT>>Если считать обращение к перемещённому объекту ошибкой, то нужны инструменты, которые могут это отслеживать на этапе компиляции. Надеюсь доживём до Lifetime profile.


A>К сожалению статический анализ имхо не закроет все темы:


Все темы может и не закроет, но в документе по ссылке ситуации с условиями вполне разбираются.
Пока сам не сделаешь...
Re[9]: Есть ли жизнь после перемещения?
От: ViTech  
Дата: 21.11.18 10:13
Оценка:
Здравствуйте, rg45, Вы писали:

R>Я бы на их месте постарался для вот этого нового move подобрать какое-нибудь более подходящее название. Например, make_rvalue, или rvalue_cast.


С точки зрения читабельности программы, на мой взгляд, move органично описывает происходящее в коде. И я бы не хотел видеть вместо move всякие make_rvalue или rvalue_cast .

R>С учетом того, что на самом деле эта функция ничего никуда не перемещает. Что часто вводит в заблуждение тех, кто только начинает вникать в имплементацию мув семантики.


То, что при этом перемещение может и не произойти, то тут скорее будет вина принимающей стороны, а не функции move.
Пока сам не сделаешь...
Re[10]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 21.11.18 10:16
Оценка: +1
Здравствуйте, ViTech, Вы писали:

R>>Я бы на их месте постарался для вот этого нового move подобрать какое-нибудь более подходящее название. Например, make_rvalue, или rvalue_cast.


VT>С точки зрения читабельности программы, на мой взгляд, move органично описывает происходящее в коде. И я бы не хотел видеть вместо move всякие make_rvalue или rvalue_cast .


Ну ты согласен, что "std::move(smth)" и "std:move(src.begin(), src.end(), dst.begin())" — это две совсем разные семантики?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[11]: Есть ли жизнь после перемещения?
От: ViTech  
Дата: 21.11.18 10:37
Оценка: :)
Здравствуйте, rg45, Вы писали:

R>Ну ты согласен, что "std::move(smth)" и "std:move(src.begin(), src.end(), dst.begin())" — это две совсем разные семантики?


Здесь да, есть некая двойственность. Возможно причины двух одинаковых имён нужно искать в истории. Если не ошибаюсь, то алгоритм move появился раньше move-семантики. И если выбирать, чему оставить имя move, то я бы выбрал move-семантику, а алгоритм переименовал. Хотя они друг другу, вроде, не мешают, и по смыслу делают одно и то же: перемещают объекты из одного места в другое.
Пока сам не сделаешь...
Re[12]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 21.11.18 10:47
Оценка:
Здравствуйте, ViTech, Вы писали:

VT>Здесь да, есть некая двойственность. Возможно причины двух одинаковых имён нужно искать в истории. Если не ошибаюсь, то алгоритм move появился раньше move-семантики. И если выбирать, чему оставить имя move, то я бы выбрал move-семантику, а алгоритм переименовал. Хотя они друг другу, вроде, не мешают, и по смыслу делают одно и то же: перемещают объекты из одного места в другое.


Нет, не делают они одно и то же, в том-то и беда. Если выражение "std::move(src.begin(), src.end(), dst.end())" вполне самостоятельно и реально что-то куда-то перемещает, то выражение "std::move(smth)" совершенно бесполезно, само по себе, и имеет смысл только как параметр, инициализатор или правая часть оператора присваивания. Здесь даже императивность в названии — "move" — и то не уместна.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 21.11.2018 10:53 rg45 . Предыдущая версия .
Re[13]: Есть ли жизнь после перемещения?
От: ViTech  
Дата: 21.11.18 11:03
Оценка:
Здравствуйте, rg45, Вы писали:

R>Нет, не делают они одно и то же, в том-то и беда. Если выражение "std::move(src.begin(), src.end(), dst.end())" вполне самостоятельно и реально что-то куда-то перемещает, то выражение "std::move(smth)" совершенно бесполезно, само по себе, и имеет смысл только как параметр, инициализатор или правая часть оператора присваивания.


Если формально подходить то да, одиночный вызов функции "std::move(smth)" смысла не имеет. Но с таким подходом и логика самой операции "перемещение" обесценивается, если объект перемещать в ... никуда . Если же исходить из смысла операции, что "что-то" перемещается "куда-то", то понимание, что std::move(smth) нужно использовать с "куда-то", должно возникать даже у начинающих программистов.
Пока сам не сделаешь...
Re[14]: Есть ли жизнь после перемещения?
От: ViTech  
Дата: 21.11.18 12:31
Оценка:
Кстати, если одиночный вызов функции "std::move(smth)" смысла не имеет, то может нужно, чтобы её в стандарте пометили как nodiscard?
Пока сам не сделаешь...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.