Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 07:32
Оценка: 6 (1)
Всем привет!

Вопрос несколько философский. Правомерно ли делать какие-либо допущения о состоянии объета, в самом общем случае, после того, как его содержимое было перемещено? Разумеется, состояние объекта должно позволять разрушить этот объект, это сомнению не прдвергается. Но достаточно ли этого? Ведь помимо физического тела у объекта есть еще и логическое состояние — его душа, так сказать. Так вот как быть с ней — нужно ли заботиться о том, чтобы после перемещения объект оставался в целостном состоянии с точки зрения логики программы — на тот случай, если кому-то захочется продолжать пользоваться объектом после его перемещения?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re: Есть ли жизнь после перемещения?
От: TimurSPB Интернет  
Дата: 20.11.18 07:49
Оценка:
R>Вопрос несколько философский. Правомерно ли делать какие-либо допущения о состоянии объета, в самом общем случае, после того, как его содержимое было перемещено? Разумеется, состояние объекта должно позволять разрушить этот объект, это сомнению не прдвергается. Но достаточно ли этого? Ведь помимо физического тела у объекта есть еще и логическое состояние — его душа, так сказать. Так вот как быть с ней — нужно ли заботиться о том, чтобы после перемещения объект оставался в целостном состоянии с точки зрения логики программы — на тот случай, если кому-то захочется продолжать пользоваться объектом после его перемещения?
В писании сказано:

Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

Как я понимаю, в общем случае нужно заботиться о целостности объекта после его перемещения.
Make flame.politics Great Again!
Re[2]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 07:59
Оценка:
Здравствуйте, TimurSPB, Вы писали:

TSP>В писании сказано:

TSP>

TSP>Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

TSP>Как я понимаю, в общем случае нужно заботиться о целостности объекта после его перемещения.

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

Этот вопрос можно сформулировать и по-другому: стоит ли требовать от разработчиков, в самом общем случае, документирования состояния объектов после перемещениея? Или исплользование объектов после перемещения — это зло, с которым нужно бороться? Или могут быть варианты?

P.S. Понятно, что из любого правила могут быть исключения. Но хотелось бы понимать, все-таки, каково же само правило.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 20.11.2018 8:06 rg45 . Предыдущая версия .
Re: Есть ли жизнь после перемещения?
От: Пирожочек  
Дата: 20.11.18 08:09
Оценка: 11 (2) +1
Здравствуйте, rg45, Вы писали:

R>Всем привет!

приветик

R>Так вот как быть с ней — нужно ли заботиться о том, чтобы после перемещения объект оставался в целостном состоянии с точки зрения логики программы — на тот случай, если кому-то захочется продолжать пользоваться объектом после его перемещения?

после перемещения объект должен поддерживать две операции — деструкцию и присваивание. Инвариант класса он поддерживать не обязан.
Re[3]: Есть ли жизнь после перемещения?
От: TimurSPB Интернет  
Дата: 20.11.18 08:09
Оценка:
R>Этот вопрос можно сформулировать и по-другому: стоит ли требовать от разработчиков, в самом общем случае, документирования состояния объектов после перемещениея? Или исплользование объектов после перемещения — это зло, с которым нужно бороться? Или могут быть варианты?
Если требуется использование объектов после перемещения и процесс разработки требует документирования всего, то да нужно. А куда деваться? В таком случае лучше всего иметь тест на валидность объекта после перемещения. И без теста пулл-реквест не апрувить.
Зло это или нет, можно определить в контексте конкретного кода. Должна быть внятная мотивация для использования перемещённых объектов, например производительность или экономия памяти. ИМХО, если можно обойтись без этого, то ну его нафиг.
Make flame.politics Great Again!
Re: Есть ли жизнь после перемещения?
От: Videoman Россия https://hts.tv/
Дата: 20.11.18 08:26
Оценка: 25 (2)
Здравствуйте, rg45:

Вопрос действительно философский. По мне, как минимум после перемещения должны работать еще две операции: swap (если есть) и присваивание (operator=).
В процессе опыта реализации перемещения разных объектов, решил что оставлять объект в валидном состоянии, в общем случае, может быть дороговато (зависит от объекта конечно), да и начинают вылезать нежелательные практики от которых, вроде как, хотелось уйти. Постараюсь объяснить что я имею ввиду:
Если строго соблюдать RAII, то в классах многих объектов отсутствуют конструкторы по умолчанию. В С++ это удобно делать если объект в "дефолтном" состоянии не имеет смысла и не может делать ничего полезного. Также такой объект не может быть в не инициализированном состоянии и не нужны внутренние проверки на валидность состояния при вызове публичных методов (максимум ассерты). Все хорошо и концепция жива пока мы не сделаем перемещение объекта. Если после перемещения продолжать работу с таким объектом, то тут же "вылезает" новое "дефолтое" состояние, такое же как в случае двойной инициализацией все преимущества RAII идут лесом.
Re: Есть ли жизнь после перемещения?
От: andyp  
Дата: 20.11.18 09:06
Оценка: :))
Здравствуйте, rg45, Вы писали:

R>Вопрос несколько философский. Правомерно ли делать какие-либо допущения о состоянии объета, в самом общем случае, после того, как его содержимое было перемещено?


Вот есть у тебя плюшевый медведь в коробке. Ты его в другую коробку переложил. Что можно сделать с коробкой? Выкинуть коробку(почему-то это будет деструктор медведя) или сунуть тем или иным способом в нее другого медведя (assignment, move опять же для медведя ). Проблема в том, что move семантика в C++ до конца не допилена имхо. В рамках системы типов ты не можешь формально отличить медведя от пустой коробки для него и все вопросы крутятся вокруг того, считать ли пустую коробку тоже медведем.
Re: Есть ли жизнь после перемещения?
От: kov_serg Россия  
Дата: 20.11.18 09:56
Оценка: +1
Здравствуйте, rg45, Вы писали:

R>Всем привет!


R>Вопрос несколько философский. Правомерно ли делать какие-либо допущения о состоянии объета, в самом общем случае, после того, как его содержимое было перемещено? Разумеется, состояние объекта должно позволять разрушить этот объект, это сомнению не прдвергается. Но достаточно ли этого? Ведь помимо физического тела у объекта есть еще и логическое состояние — его душа, так сказать. Так вот как быть с ней — нужно ли заботиться о том, чтобы после перемещения объект оставался в целостном состоянии с точки зрения логики программы — на тот случай, если кому-то захочется продолжать пользоваться объектом после его перемещения?


У меня другой философский вопрос: Стоило вводить move семантику вообще что бы потом иметь дополнительные проблемы или можно было обойтись дополнительным стеком для каждого потока не приязанного с стеку вызовов?
Re: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 20.11.18 10:32
Оценка:
Здравствуйте, rg45, Вы писали:

R>нужно ли заботиться о том, чтобы после перемещения объект оставался в целостном состоянии с точки зрения логики программы — на тот случай, если кому-то захочется продолжать пользоваться объектом после его перемещения?



1) IMHO, вопрос хороший. С ещё одной стороны показывает насколько убога концепция мув-семантики.

2) Опять же, IMHO, нужно идти от того, какие сценарии, с использованием оставшегося после перемещения объекта, мы считаем валидными.
В простых сценариях, вроде отдали/передали временное значение, или то, что больше не хотим использовать, ясно, что использование объекта, данные из которого перемещены, само по себе подозрительно, но, к сожалению, есть сценарии, вроде вставки/удаления элемента в середине массива, например.

Есть ли ещё какие-то вменяемые сценарии, в которых постперемещённые объекты как-то используются?


3) Если все нужды сводятся к (2), то я бы вообще от мув-семантики отказался, во всяких передачах/заменах использовал бы RVO/NRVO, а для перемещений из буфера в буфер массивов элементов завёл бы специальную шаблонную функцию, которую бы пользователи STL могли бы для своих типов перекрывать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[2]: Есть ли жизнь после перемещения?
От: Videoman Россия https://hts.tv/
Дата: 20.11.18 13:25
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>У меня другой философский вопрос: Стоило вводить move семантику вообще что бы потом иметь дополнительные проблемы или можно было обойтись дополнительным стеком для каждого потока не приязанного с стеку вызовов?


А можно поподробней, что имеется ввиду? Это другая модель абстрактной машины что ли? Так это уже не С вовсе будет, не?
Re[2]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 14:10
Оценка:
Здравствуйте, kov_serg, Вы писали:

_>У меня другой философский вопрос: Стоило вводить move семантику вообще что бы потом иметь дополнительные проблемы или можно было обойтись дополнительным стеком для каждого потока не приязанного с стеку вызовов?


А что такое "move семантика вообще"? Это:

1) Новый тип ссылок, позволяющий, обработать временный объект по-другому, чем не временный;
2) Операция move, позволяющая обработать не временный объект, как временный.

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

А с возможностью форвардинга как быть? От нее тоже отказываемся?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 14:21
Оценка: +1
Здравствуйте, andyp, Вы писали:

A>Вот есть у тебя плюшевый медведь в коробке. Ты его в другую коробку переложил. Что можно сделать с коробкой? Выкинуть коробку(почему-то это будет деструктор медведя) или сунуть тем или иным способом в нее другого медведя (assignment, move опять же для медведя ). Проблема в том, что move семантика в C++ до конца не допилена имхо. В рамках системы типов ты не можешь формально отличить медведя от пустой коробки для него и все вопросы крутятся вокруг того, считать ли пустую коробку тоже медведем.


Здесь проблема скорее в выбранной аналогии, чем собственно в move семантике. Замени "Коробка и медведь" на "медведь и опилки" и степень удивленности резко снизится
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Есть ли жизнь после перемещения?
От: B0FEE664  
Дата: 20.11.18 14:23
Оценка: +2
Здравствуйте, kov_serg, Вы писали:

_>У меня другой философский вопрос: Стоило вводить move семантику вообще что бы потом иметь дополнительные проблемы или можно было обойтись дополнительным стеком для каждого потока не приязанного с стеку вызовов?


У меня другой философский вопрос: если вам не нравится move семантика, то зачем ею пользоваться? Не пользуйтесь и вы не заметите изменений почти никогда.
И каждый день — без права на ошибку...
Re[2]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 14:23
Оценка:
Здравствуйте, Erop, Вы писали:

E>1) IMHO, вопрос хороший. С ещё одной стороны показывает насколько убога концепция мув-семантики.


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

E>2) Опять же, IMHO, нужно идти от того, какие сценарии, с использованием оставшегося после перемещения объекта, мы считаем валидными.


Так это я об этом спрашиваю, вообще-то
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Есть ли жизнь после перемещения?
От: ViTech  
Дата: 20.11.18 14:29
Оценка: 17 (2) +1
Здравствуйте, TimurSPB, Вы писали:

TSP>В писании сказано:

TSP>

TSP>Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

TSP>Как я понимаю, в общем случае нужно заботиться о целостности объекта после его перемещения.

Считаю, что нужно ещё начало выделить:

Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.


И понимаю так, что в писании valid but unspecified state относится к objects of types defined in the C++ standard library, а не ко всем типам, написанным на C++ вообще. Т.е. в своих классах можно и другого поведения придерживаться. Но я тоже сторонник того, что перемещённый объект можно или удалить, или присвоить ему новое значение. И не пытаться использовать его, пусть он хоть и в valid but unspecified state. Т.е. души/сущности у перемещённого объекта нет, остаётся только оболочка .
Пока сам не сделаешь...
Re[3]: Есть ли жизнь после перемещения?
От: andyp  
Дата: 20.11.18 14:40
Оценка: 5 (1)
Здравствуйте, rg45, Вы писали:

R>Здесь проблема скорее в выбранной аналогии, чем собственно в move семантике. Замени "Коробка и медведь" на "медведь и опилки" и степень удивленности резко снизится


Ну вот смотри, у Степанова в книжке я первый первый раз подход к снарядам на эту тему встретил. (На самом деле он там про эффективный swap пишет). Так вот, он там вводит понятие UnderlyingType<T>:

The implementation of the underlying type for an original type T is
straightforward and could be automated. U = UnderlyingType(T) always has the same layout as
the header of T. The copy constructor and assignment for U just copy the bits; they
do not construct a copy of the remote parts of T
.


swap в его исполнении выглядит как

template<typename T> 
requires(Regular(T)) 
void swap(T& x, T& y) 
{ 
    UnderlyingType(T) tmp = underlying_ref (x) ; 
    underlying_ref (x) = underlying_ref (y) ; 
    underlying_ref (y) = tmp; 
}


Т.е. он уже начал подумывать как различать мишку, коробку и мишку в коробке. Имхо, в стране розовых пони, если ты смувил из объекта, его тип должен автоматически переключаться на Вох<T> и не давать тебе с таким объектом шалить. Сама концепция такой коробки тоже достаточно полезна имхо.
Re: Есть ли жизнь после перемещения?
От: B0FEE664  
Дата: 20.11.18 14:46
Оценка:
Здравствуйте, rg45, Вы писали:

R>Вопрос несколько философский. Правомерно ли делать какие-либо допущения о состоянии объета, в самом общем случае, после того, как его содержимое было перемещено?


Я придерживаюсь той философии, что после перемещения объект можно только разрушить вызвав деструктор (что, как правило, происходит автоматически), а больше с перемещённым объектом ничего делать не следует.
И каждый день — без права на ошибку...
Re[4]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 14:47
Оценка:
Здравствуйте, andyp, Вы писали:

A>Ну вот смотри, у Степанова в книжке я первый первый раз подход к снарядам на эту тему встретил. (На самом деле он там про эффективный swap пишет). Так вот, он там вводит понятие UnderlyingType<T>:


A>Т.е. он уже начал подумывать как различать мишку, коробку и мишку в коробке. Имхо, в стране розовых пони, если ты смувил из объекта, его тип должен автоматически переключаться на Вох<T> и не давать тебе с таким объектом шалить. Сама концепция такой коробки тоже достаточно полезна имхо.


Степанов — это Степанов, мишка — это мишка, а коробка — это коробка. Я полагаю, что вещи лучше, все-таки, называть своими именами и не смешивать одно с другим.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 14:54
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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


Я, в общем-то придеживаюсь близких взлядов, но формулирую их чуть по-другому: "не следует применять операцию move к объекту, который предполагается еще использовать". Вроде бы, одно и то же, но звучит более логично, имхо.

А как насчет операции присваивания (или reset какой-нибудь)? Я не вижу причин, фигурально выражаясь, запрещать возможность вдохнуть в объект новую жизнь.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[5]: Есть ли жизнь после перемещения?
От: andyp  
Дата: 20.11.18 14:55
Оценка:
Здравствуйте, rg45, Вы писали:

R>Степанов — это Степанов, мишка — это мишка, а коробка — это коробка. Я полагаю, что вещи лучше, все-таки, называть своими именами и не смешивать одно с другим.


Извини, я не имел возможности всё это серьезно продумать, поэтому могло выйти невнятно. Надеюсь, всё же, моя позиция по вызовы деструкторов объектов, которые уже переместили, достаточно ясна — не смысла это делать для того, чего уже там нет. И уж тем более нет смысла в деструкторе объекта отслеживать, осталась от него только оболочка или нет.
Re[4]: Есть ли жизнь после перемещения?
От: ViTech  
Дата: 20.11.18 15:30
Оценка:
Здравствуйте, andyp, Вы писали:

A> Т.е. он уже начал подумывать как различать мишку, коробку и мишку в коробке. Имхо, в стране розовых пони, если ты смувил из объекта, его тип должен автоматически переключаться на Вох<T> и не давать тебе с таким объектом шалить. Сама концепция такой коробки тоже достаточно полезна имхо.


Если считать обращение к перемещённому объекту ошибкой, то нужны инструменты, которые могут это отслеживать на этапе компиляции. Надеюсь доживём до Lifetime profile.
Пока сам не сделаешь...
Re[5]: Есть ли жизнь после перемещения?
От: andyp  
Дата: 20.11.18 16:10
Оценка:
Здравствуйте, ViTech, Вы писали:

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


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

void test(bool condition)
{
    A a,b;
    if(condition)
    {
        b = std::move(a);    
    }    
    //а пусто или полно? В статике не узнать.
    //сейчас деструктор будет вызван вне зависимости от.
}
Re[3]: Есть ли жизнь после перемещения?
От: B0FEE664  
Дата: 20.11.18 16:21
Оценка: 16 (1)
Здравствуйте, rg45, Вы писали:

R>А как насчет операции присваивания (или reset какой-нибудь)? Я не вижу причин, фигурально выражаясь, запрещать возможность вдохнуть в объект новую жизнь.


На практике (кроме как внутри swap), никакого присваивания к перемещённому объекту у меня желания сделать не возникало. Допускаю, что возможно это связано с теми задачами, что я решаю. Я почти не пишу шаблонного кода последние 6 месяцев. А вообще, наверное можно подходить так: объект — это интерфейс + данные. Перемещение уносит данные из объекта. Объект без данных — это просто интерфейс. Соответственно, чтобы продолжать работу с объектом, его надо наполнить данными. Как-то так.
И каждый день — без права на ошибку...
Re[4]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 16:25
Оценка:
Здравствуйте, B0FEE664, Вы писали:


R>>А как насчет операции присваивания (или reset какой-нибудь)? Я не вижу причин, фигурально выражаясь, запрещать возможность вдохнуть в объект новую жизнь.


BFE>На практике (кроме как внутри swap), никакого присваивания к перемещённому объекту у меня желания сделать не возникало. Допускаю, что возможно это связано с теми задачами, что я решаю. Я почти не пишу шаблонного кода последние 6 месяцев. А вообще, наверное можно подходить так: объект — это интерфейс + данные. Перемещение уносит данные из объекта. Объект без данных — это просто интерфейс. Соответственно, чтобы продолжать работу с объектом, его надо наполнить данными. Как-то так.


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

E>>1) IMHO, вопрос хороший. С ещё одной стороны показывает насколько убога концепция мув-семантики.

R>Не могу согласиться, при всем уважении. ИМХО, это скорее показывает какой-то неудачный опыт применения.
А какой код упростился? Стал удобнее, поддерживаемее или ещё в чём-то лучше?
То, что теперь надо у всех встречных поперечных классов ещё один конструктор и оператор присваивания писать, вряд ли можно считать за упрощение кода?
В целом быстродействие/память только в редких бутылочных горлышках критичны, а мов-семантика расползается по всему коду...

При этом она противоречит чистому RAII, требует существования "пустого" состояния объектов, не может нормально работать с большими объектами размещёнными на стеке, в отличии от RVO и т. д...


E>>2) Опять же, IMHO, нужно идти от того, какие сценарии, с использованием оставшегося после перемещения объекта, мы считаем валидными.


R>Так это я об этом спрашиваю, вообще-то


Ну я знаю только один такой сценарий -- вставку/удаление элемента в массив.
И на мой взгляд ради этой операции мутить семантику перемещения в языке -- это оверкил был...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Есть ли жизнь после перемещения?
От: B0FEE664  
Дата: 20.11.18 16:38
Оценка:
Здравствуйте, rg45, Вы писали:

R>>>А как насчет операции присваивания (или reset какой-нибудь)? Я не вижу причин, фигурально выражаясь, запрещать возможность вдохнуть в объект новую жизнь.

R>Ну то есть, скорее "да", чем "нет", можно присваивать, правильно я тебя понял?

Скорее "да", чем "нет", но прошу учесть, что это мнение, а не знание.
И каждый день — без права на ошибку...
Re[4]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 17:43
Оценка: +2
Здравствуйте, Erop, Вы писали:

E>А какой код упростился? Стал удобнее, поддерживаемее или ещё в чём-то лучше?


Очень много чего упростилось. Перечислять не стану, примеров просто бездна.

E>То, что теперь надо у всех встречных поперечных классов ещё один конструктор и оператор присваивания писать, вряд ли можно считать за упрощение кода?


Кому надо-то? Если ты будешь писать, как писал на C++03, никакой мув семантики ты даже не заметишь. Добавились новые возможности, но добавились ненавязчиво — хочешь используй, хочешь нет.

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


Что значит, она расползается? Используй только там, где она реально приносит пользу, а не где попало, и ничего никуда расползаться не будет.

E>При этом она противоречит чистому RAII, требует существования "пустого" состояния объектов, не может нормально работать с большими объектами размещёнными на стеке, в отличии от RVO и т. д...


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

R>Очень много чего упростилось. Перечислять не стану, примеров просто бездна.

Раз очень много чего, то, наверное, не трудно привести три-пять примеров? А то я не уверен, что мы одинаково понимаем слово "упростилось"...

R>Кому надо-то? Если ты будешь писать, как писал на C++03, никакой мув семантики ты даже не заметишь. Добавились новые возможности, но добавились ненавязчиво — хочешь используй, хочешь нет.


Ужасная история по мотивам охоты за багой.
1) У нас есть класс -- авторегистрилка в уведомлялке.
Если нам надоть на что-то подписаться, мы из этой штуки выводимся, и она сама подписывается/отписывется все дела.
2) Что бы можно было юзать RVO, эта авторегистрика умеет конструктор копии, который при RVO всё не зовут, но если позовут, вдруг, ну будет два подписывания/отписывания вместо одного.
3) Мы разводим три вагона каких-то классов, у которых куча авторегистрилок в базах, что бы куда-то регаться/разрегиваться и всё такое.

// тут мы переходим от C++03 к более совершенным версиям


4) Авторигестрилке приписывают move-конструктор, который заменяет подписчика в списке источника уведомлений, вместо того, что бы массив туда-сюда двигать

5) В каких-то случаях случаются странные эффекты при вызовах автосгенерированных move-конструкторов...

Ну и в сложных конструкциях всяких таких хитрых эффектов скока хочешь приключается.

R>Как это RAII может конфликтовать с move семантикой, интересно?

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

R>Ну взять классику жанра — смартпоинтеры. В них во все сейчас подобавляли перемещающие конструкторы и операторы присваивания. При этом места их использования никак менять не пришлось, просто код стал более эффективным, порой чувствительно.


А вот представь себе, что были бы смарт-ссылки? У смартпоинтеров есть "нулевое" состояние, в отличии от чистого RAII

R>В тех местах, где раньше происходило копирование смартпоинтера, выполнялась интерлокед операция и сбрасывался кэш процессора, сейчас происодит move, который сводится к переброско одного несчастного указателя — все!

Речь идёт о возврате из функций? Чаще всего с этим справлялось RVO…
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 20.11.18 18:04
Оценка:
Здравствуйте, rg45, Вы писали:

R>Я, в общем-то придеживаюсь близких взлядов, но формулирую их чуть по-другому: "не следует применять операцию move к объекту, который предполагается еще использовать". Вроде бы, одно и то же, но звучит более логично, имхо.



А удаление объекта из середины массива, путём цепочки перемещений, ты валидным не считаешь разве?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 20.11.18 18:08
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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



Разве вставка не в конец в std::vector сейчас не через цепочку move-конструкторов/присваиваний работает?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 18:35
Оценка: +1
Здравствуйте, Erop, Вы писали:

R>>Я, в общем-то придеживаюсь близких взлядов, но формулирую их чуть по-другому: "не следует применять операцию move к объекту, который предполагается еще использовать". Вроде бы, одно и то же, но звучит более логично, имхо.


E>А удаление объекта из середины массива, путём цепочки перемещений, ты валидным не считаешь разве?


Считаю. Мы это обсудили уже, ниже по ветке.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[6]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 19:06
Оценка: +2
Здравствуйте, Erop, Вы писали:

E>Раз очень много чего, то, наверное, не трудно привести три-пять примеров? А то я не уверен, что мы одинаково понимаем слово "упростилось"...


Например, можно стало смелее оперировать с коллекциями тяжелых объектов, не боясь переаллокаций, ушла необходимость в лишней косвенности. Многие классы, для которых трудно и нецелесообразно пледоставлять копирование вполне поддаются перемещению, зачастую очень простому и дешевому. Проще стало возвращать значения из фунцкций — если не отработает RVO/NRVO, по каким-то причинам, то move точно не подведет. Не нужно ломать голову, какой выбрать умный указатель, чтобы вернуть из функции некопируемый объект. Уменшьшилась потребность в аутпут параметрах, что в целом положительно отразилось на общей структуре кода. Например, запросто можно позволить себе такое вот простейшую и в тоже время очень юзабельную реализацию дерева. Причем, деревья эти могут иметь какую угодно сложность, а все манипуляции с ними будут не тяжелее, чем с парой простых указаделей. И это гарантировано, потому, что в данном случае копирование запрещено, разрешено только перемещение:

template <typename T>
class Tree : public std::vector<Tree<T>>
{
public:

  template <typename...U>
  explicit Tree(U&&...u) : m(std::forward<U>(u)...) {}
  
  // Movable but non-copyable
  Tree(Tree&&) = default;
  Tree& operator = (Tree&&) = default;

  T& operator* () { return m; }
  const T& operator* () const { return m; }

private:
  T m;
};


R>>Кому надо-то? Если ты будешь писать, как писал на C++03, никакой мув семантики ты даже не заметишь. Добавились новые возможности, но добавились ненавязчиво — хочешь используй, хочешь нет.


E>Ужасная история по мотивам охоты за багой.

E>...
E>Ну и в сложных конструкциях всяких таких хитрых эффектов скока хочешь приключается.

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

E>Если мы RAII объект мувим, то на старом месте остаётся существующий объект, которому не соответствует никакой ресурс.


То на старом месте остается указатель или хэндл ресурса просто обнуляется, как обнуляется указатель в смарт-поинтере. В более сложном случае мув семантика просто не поддерживается и заменяется на копирование. Только существование таких более сложных случаев вовсе не отменяет эффективности мув в семаники во всех других случаях.

E>А вот представь себе, что были бы смарт-ссылки? У смартпоинтеров есть "нулевое" состояние, в отличии от чистого RAII


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

E>Речь идёт о возврате из функций? Чаще всего с этим справлялось RVO…


Ага, чаще всего справлялось. Только разработчики зачастую говорили/думали: "да ну его нафиг, этот РВО, х.з. отработает или нет, заведу-ка я аутпут параметр..."
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 20.11.2018 19:44 rg45 . Предыдущая версия . Еще …
Отредактировано 20.11.2018 19:43 rg45 . Предыдущая версия .
Отредактировано 20.11.2018 19:11 rg45 . Предыдущая версия .
Отредактировано 20.11.2018 19:07 rg45 . Предыдущая версия .
Re[7]: Есть ли жизнь после перемещения?
От: lpd Черногория  
Дата: 20.11.18 20:01
Оценка:
Здравствуйте, rg45, Вы писали:

R>Например, можно стало смелее оперировать с коллекциями тяжелых объектов, не боясь переаллокаций, ушла необходимость в лишней косвенности.

Прощай лишняя косвенность, здравствуй rvalue reference.

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

Сложно придумать пример класса, для которого копирование реализовать сложнее, чем перемещение. И зачем экономить на копировании большинства классов?

R> Проще стало возвращать значения из фунцкций — если не отработает RVO/NRVO, по каким-то причинам, то move точно не подведет.

Я понял, у тебя фобия лишней косвенности. Могу напомнить: под капотом у rvalue reference все то же самое.

R> Не нужно ломать голову, какой выбрать умный указатель, чтобы вернуть из функции некопируемый объект.

Допустим(это я не понял, особенно зачем ты часто подобными проблемами мучаешься).

R> Уменшьшилась потребность в аутпут параметрах, что в целом положительно отразилось на общей структуре кода.

Я все таки на всякий случай спрошу: надеюсь, ты не всем вподряд типам добавляешь move-конструкторы?
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[8]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 20:11
Оценка:
Здравствуйте, lpd, Вы писали:

lpd>Прощай лишняя косвенность, здравствуй rvalue reference.


Как пример упрощения. Без косвенности проще, чем с ковенностью.

lpd>Сложно придумать пример класса, для которого копирование реализовать сложнее, чем перемещение. И зачем экономить на копировании большинства классов?


Запросто, смотри

class PhysicalWorld
{
public:

  PhysicalWorld();
  PhysicalWorld(PhysicalWorld&&) = default;
  PhysicalWorld& operator = (PhysicalWorld&&) = default;

  // Задолбишься пыль глотать.
  // Да и нафиг не нужно никому.
  // Поэтому non-copyable
  PhysicalWorld(const PhysicalWorld&) = delete;
  PhysicalWorld& operator = (const PhysicalWorld&) = delete;

private:
  class Impl;
  std::inique_ptr<Impl> m {};
};


R>> Проще стало возвращать значения из фунцкций — если не отработает RVO/NRVO, по каким-то причинам, то move точно не подведет.

lpd>Я понял, у тебя фобия лишней косвенности. Могу напомнить: под капотом у rvalue reference все то же самое.

Где ты тут что про косвенность нашел

lpd>Допустим(это я не понял, особенно зачем ты часто подобными проблемами мучаешься).


Ну потому что я иногда не только палочкой окаменелые какашки ковыряю, как некоторые.

lpd>Я все таки на всякий случай спрошу: надеюсь, ты не всем вподряд типам добавляешь move-конструкторы?


Нет, конечно. Зачем же мне у компилятора отбирать его работу. А там где добавляю, то чаще всего как default, как в примере выше. Странное у тебя представленние о поддержке мув-семантики, надо сказать.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 20.11.2018 20:16 rg45 . Предыдущая версия . Еще …
Отредактировано 20.11.2018 20:12 rg45 . Предыдущая версия .
Re[9]: Есть ли жизнь после перемещения?
От: lpd Черногория  
Дата: 20.11.18 20:21
Оценка:
Здравствуйте, rg45, Вы писали:

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


lpd>>Я все таки на всякий случай спрошу: надеюсь, ты не всем вподряд типам добавляешь move-конструкторы?


R>Нет, конечно. Зачем же мне у компилятора отбирать его работу. А там где добавляю, то чаще всего как default, как в примере выше. Странное у тебя представленние о поддержке мув-семантики, надо сказать.


Имею ввиду: надеюсь, не всегда используешь move-семантику и rvalue-reference, где возможно? Ради каких крох производительности ты на это заморачиваешься?
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[10]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 20.11.18 20:25
Оценка:
Здравствуйте, lpd, Вы писали:

R>>Нет, конечно. Зачем же мне у компилятора отбирать его работу. А там где добавляю, то чаще всего как default, как в примере выше. Странное у тебя представленние о поддержке мув-семантики, надо сказать.


lpd>Имею ввиду: надеюсь, не всегда используешь move-семантику и rvalue-reference, где возможно? Ради каких крох производительности ты на это заморачиваешься?


Что значит, "я не использую", когда зачастую мув семантика доступна по умолчанию и нужно сделать дополнительные телодвижения для того, чтобы ее запретить? Я разверну тебе твой вопрос: ради чего ты предлагаешь заморачиваться, чтобы побороть доступную по умолчанию мув семантику?

Как ты не поймешь, что "поддержка мув семантике" это совсем не означает добление по клавишам. Чаше всего этот процесс происходит в голове — это просто осмысленное отношение к коду, который выходит из под твоих пальцев.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 20.11.2018 20:28 rg45 . Предыдущая версия .
Re[11]: Есть ли жизнь после перемещения?
От: lpd Черногория  
Дата: 20.11.18 20:32
Оценка:
Здравствуйте, rg45, Вы писали:

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


lpd>>Имею ввиду: надеюсь, не всегда используешь move-семантику и rvalue-reference, где возможно? Ради каких крох производительности ты на это заморачиваешься?


R>Что значит, "я не использую", когда зачастую мув семантика доступна по умолчанию и нужно сделать дополнительные телодвижения для того, чтобы ее запретить? Я разверну тебе твой вопрос: ради чего ты предлагаешь заморачиваться, чтобы побороть доступную по умолчанию мув семантику?


Я не особенно часто ее использовал, и если она доступна по умолчанию, это хорошо, хотя я и сильно сомневаюсь, что она по умолчанию доступна столь часто.
Я предлагаю не использовать move-семантику почти никогда, ради того, чтобы просто присваивать переменные, как это всегда делалось, и не возиться с запутанными правилами преобразования rvalue-reference. Не замусоривать код всеми этими std::move, которые нужно держать в голове, и которые абсолютно ничего не дают, кроме десятых долей процента быстродействия программы, которыми можно пренебречь.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Re[7]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 20.11.18 20:40
Оценка:
Здравствуйте, rg45, Вы писали:

R>Например, можно стало смелее оперировать с коллекциями тяжелых объектов, не боясь переаллокаций, ушла необходимость в лишней косвенности. Многие классы, для которых трудно и нецелесообразно пледоставлять копирование вполне поддаются перемещению, зачастую очень простому и дешевому.


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

Смотри, одна история — это дефект дизайна std::vector, так как он не умеет move-семантику на уровне библиотеки, а не языка.
Ну да он много чего не умел в С++98, впрочем и сейчас не до конца выпрямился.
В любом случае, были более или менее простые решения, вроде стандартизации шаблонной функции вроде
template<typename T>
void move_vector_item( void* dst, T* src )
{
    assert( src != 0 && dst != 0 && dst != src );
    ::new( dst ) T( *src );
    src->~T()
}


template<typename T>

void move_vector_buffer( void* dst, T* begin, T* end )
{
    //  Тут выбираем правильное направление обхода и в цикле зовём move_vector_item
}


Ну и для нужных типов переопределяем, как раньше со swap делали.


R>Проще стало возвращать значения из фунцкций — если не отработает RVO/NRVO, по каким-то причинам, то move точно не подведет.

Во-первых, не все быстрые типы хорошо поддаются move.
Скажем, если у нас строчки устроены так, что короткие строки лежат в буфере прямо "на борту" объекта, то их перемещение будет так же дорого, как копирование.
При этом у RVO/NRVO такой проблемы нет.
Я бы предпочёл какие-то средства явно управлять RVO/NRVO, например...


R>Не нужно ломать голову, какой выбрать умный указатель, чтобы вернуть из функции некопируемый объект. Уменшьшилась потребность в аутпут параметрах, что в целом положительно отразилось на общей структуре кода. Например, запросто можно позволить себе такое вот простейшую и в тоже время очень юзабельную реализацию дерева. Причем, деревья эти могут иметь какую угодно сложность, а все манипуляции с ними будут не тяжелее, чем с парой простых указаделей. И это гарантировано, потому, что в данном случае копирование запрещено, разрешено только перемещение:


Пример прикольный, но представь себе, что был бы метод move у std::vector'а… (И у этого дерева тоже, соответственно)
Какой клиентский код бы усложнился?


R>>>Кому надо-то? Если ты будешь писать, как писал на C++03, никакой мув семантики ты даже не заметишь. Добавились новые возможности, но добавились ненавязчиво — хочешь используй, хочешь нет.


E>>Ужасная история по мотивам охоты за багой.

R>Я тебе таких историй могу тоже рассказать вагон и маленькую тележку. Только все эти истории будут про кривые руки, а не про проблемы мув семантики.

Так это была история про то, что move-семантика умеет расползаться...
И, кстати, в рассказанной истории я не совсем понял, в каком месте были такие уж супер-кривые руки?


E>>Если мы RAII объект мувим, то на старом месте остаётся существующий объект, которому не соответствует никакой ресурс.

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

R>Ага, чаще всего справлялось. Только разработчики зачастую говорили/думали: "да ну его нафиг, этот РВО, х.з. отработает или нет, заведу-ка я аутпут параметр..."

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

На самом деле есть ещё один аспект move-семантики. Связывание неконстантных ссылок с временными объектами.

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


В общем резюме моего мнения такое:
1) Безусловно move-семантика в stl-коллекциях была нужна и её не хватало. Но, на мой взгляд её надо было вводить на уровне библиотеки, тем более, что сейчас такую move-семантику прибили гвоздями и опять сказали "нет" развитию библиотеки.

2) То, что NRVO/RVO имело какой-то факультативный статус, было криво. Вместо того, что бы сделать его более явным и управляемым, сделали std::move, который не всегда понятно что сделает, да ещё и является ещё одним альтернативным способом для того же самого, что только усложняет поведение компилятора, и без того не простое.

3) В связывании временных объектов со ссылками тоже навели ещё больше сложностей, вместо того, что бы упростить.

4) Сама по себе нынешняя концепция перемещающего конструктора, если вообще считать, что такой нужен, кривая, так как заставляет оставлять на месте источника некое "пустое" состояние. Было бы логичнее в случае вызова какой-то такой конструкции исходный объект РАЗРУШАТЬ...
Правда тогда бы в некоторых случаях было бы что-то недоступно из того, что доступно сейчас. Но мне кажется, что никаких полезных сценариев бы не потерялось...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Есть ли жизнь после перемещения?
От: Videoman Россия https://hts.tv/
Дата: 20.11.18 20:46
Оценка: +1
Здравствуйте, Erop, Вы писали:

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

E>5) В каких-то случаях случаются странные эффекты при вызовах автосгенерированных move-конструкторов...

Т.е. кто-то не разобрался как правильно реализовывать move семантику и зачем-то неправильно переопределил move-конструктор?

E>Ну и в сложных конструкциях всяких таких хитрых эффектов скока хочешь приключается.


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

E>Классический RAII это объект есть -- ресурс захвачен, объект разрушен -- ресурс освобождён.

E>Если мы RAII объект мувим, то на старом месте остаётся существующий объект, которому не соответствует никакой ресурс.

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

E>А вот представь себе, что были бы смарт-ссылки? У смартпоинтеров есть "нулевое" состояние, в отличии от чистого RAII


В данном случае поведение смарт-ссылок нечем не отличается от просто-ссылок. Перемещается не ссылка, а сам объект. Если в вашем случае недопустимо такое состояние объекта не используйте std::move для l-value ссылок.

E>Речь идёт о возврате из функций? Чаще всего с этим справлялось RVO…


Я не уверен, но речь скорее всего идет о std::smart_ptr, где используется атомарный счетчик ссылок внутри.
Но вообще, с приходом move-семантики появилась возможность безопасно выражать в коде поведение объектов которые невозможно скопировать, но можно передать владение ими, например: thread, file, uniqe_ptr и т.д.
Re[7]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 20.11.18 20:59
Оценка:
Здравствуйте, Videoman, Вы писали:

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


V>Т.е. кто-то не разобрался как правильно реализовывать move семантику и зачем-то неправильно переопределил move-конструктор?

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

V>Если вы пока не решили как с такими состояниями правильно работать, просто не допускайте ручного вызова std::move для l-value.

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

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


Почему бы его не выражать просто методом move?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
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?
Пока сам не сделаешь...
Re[15]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 21.11.18 12:35
Оценка: +1
Здравствуйте, ViTech, Вы писали:

VT>Кстати, если одиночный вызов функции "std::move(smth)" смысла не имеет, то может нужно, чтобы её в стандарте пометили как nodiscard?


Я всегда придерживался и придерживаюсь мнения, что вещи лучше называть своими именами, а функциям давать названия, соответствующие производимому ими эффекту. Исходя из этого, move — не очень удачный выбор, ИМХО.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[16]: Есть ли жизнь после перемещения?
От: ViTech  
Дата: 21.11.18 16:00
Оценка:
Здравствуйте, rg45, Вы писали:

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


Я согласен с таким подходом и тоже стараюсь его придерживаться. Собственно, исходя из конечного эффекта, который функция move производит в выражении, в котором она употребляется, я и считаю её название подходящим (тоже ИМХО) .

В выражении b = a выполняется копирование, в выражении b = std::move(a) происходит перемещение внутренностей из a в b, в этом смысл действия, а не в преобразовании типов. Технически да, с одной стороны (b) принимается параметр в виде rvalue-ссылки, с другой (a) — преобразование в rvalue-ссылку, чтобы "совместилось" с нужным конструктором/оператором/методом. Но далее фактически выполняется перемещение. А rvalue-ссылки — это всего лишь механизм/реализация, существующие на текущий момент (до C++11 их не было, есть гарантии, что в С++32 не появятся другие?). Конструкторы же тоже называют copy/move constructors, а не lvalue/rvalue constructors, т.е. по смыслу операции, а не по фактическим параметрам. Ну и, в конечном итоге, лично мне приятнее и понятнее в программе видеть b = std::move(a), а не b = rvalue_cast(a). Но это уже дело вкуса.

Вот такое у меня оправдание названия для move .
Пока сам не сделаешь...
Re[7]: Есть ли жизнь после перемещения?
От: andyp  
Дата: 21.11.18 19:31
Оценка:
Здравствуйте, ViTech, Вы писали:

VT>Все темы может и не закроет, но в документе по ссылке ситуации с условиями вполне разбираются.


Видел. Не очень-то с ними разбираются. Просто действуют, предполагая, что худший сценарий возможен, выдавая диагностику, если указатель провис в хотя бы одной из веток условия. Для вызова методов возможно перемещенного объекта по логике то же самое наверное предлагается.
Re[17]: Есть ли жизнь после перемещения?
От: Пирожочек  
Дата: 21.11.18 21:43
Оценка: +1
Здравствуйте, ViTech, Вы писали:


VT>Я согласен с таким подходом и тоже стараюсь его придерживаться. Собственно, исходя из конечного эффекта, который функция move производит в выражении, в котором она употребляется, я и считаю её название подходящим (тоже ИМХО) .


вот что дедушка пишет по этому поводу

move(x) means 'give me an rvalue reference to x.' That is, std::move(x) does not move anything; instead, it allows a user to move x. It would have been better if move() had been called rval(), but the name move() has been used for this operation for years


и я с ним полностью согласен. move ничего не мувает, а всего лишь кастит к rvalue-ссылке, поэтому название у функции не совсем корректно.
Отредактировано 21.11.2018 21:44 Пирожочек . Предыдущая версия .
Re[11]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 22.11.18 07:29
Оценка:
Здравствуйте, Videoman, Вы писали:

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


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

Ну так нужен анализ их важности.
При этом RVO всё равно остался самым логичным механизмом на эту тему, так как фактически RVO -- это синтаксический сахар вокруг возврата результата через параметр.
Так что и дальше можно обсуждать механизмы по управлению RVO...

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


Конструктор копии был всегда, в отличии от. То, как сделали move-семантику, неизбежно приводит к тому, что она тихо и автоматически расползается по коду. Я считаю это одним из недостатков, а ты?

V> и move-конструктор не подойдет, его нужно переопределить.

Даже это утверждение неверное, к сожалению. Я знаю примеры, когда дефолтный конструктор копии работает корректно, а дефолтный конструктор перемещения -- нет. Причём молча с очень отдалёнными последствиями.

V>Но это все только в том случае, если вы решите осознанно использовать move. Если вы его явно не определите, тое компилятор сам запретит его использование, за вас и старый код не поломается.

Если библиотечные базы его начнут использовать, то всё не так радужно

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


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

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


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

Я не предлагаю решение, я просто показываю, что то как сделали является вовсе не единственной альтернативой. На моё взгляд главная проблема, которую чинил move-конструктор -- это кривой дизайн std::vector со товарищи...
При этом его так и не выпрямили


V>По умолчанию, сама она к вам не придет. Для этого, как минимум, нужно начать определять свои move-конструкторы. Я уже написал выше почему.


Это так в маленьких, свеженьких, компактных сфероконновакуумных проектах так. Если речь о чём-то вроде MSWord, например, или ещё более развесистом и старом проекте, то там нет выбора включать или нет. Либо на уровне проекта новшество просто запрещается полностью, либо оно так устроено, что оно не умеет саморасползаться, как, например, auto или лямбды, либо оно расползается по везде, просто как раковые метастазы. В этом смысле move-семантика примерно на грани онкологии...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[13]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 22.11.18 07:47
Оценка:
Здравствуйте, rg45, Вы писали:

R>Есть старый и мы хотим создать новый, переместив в него содержимое из старого.


1) Почему бы сразу не создавать новый? Так же как NRVO это делает? Мы же про альтернативные изменения языка говорим, да?
2) Когда мы получаем из функции объект, на самом деле вызывающая сторона на своём фрейме выделяет память для этого объекта, и передаёт в вызываемую функцию адрес, куда помещать результат. Потом вызываемая там его создаёт, и отдаёт управление, а вызывающая начинает им владеть.
При NRVO компилятор так меняет код вызываемой функции, что объект, "копию" которого потом будут возвращать, создаётся сразу в переданном буфере, и потом он и остаётся в качестве результата функции.

Понятно, что эту пару механизмов (передача места под результат на внешнем фрейме через скрытый параметр и отображение разных видных как последовательно существующие копии объектов на один и тот же буфер) можно применять рекурсивно и многократно.


Как-то похоже работают и конструкторы, кстати.

То, что у нас, как программистов на С++ нет механизмов для прямого написания похожих функций, ну, например, мы не можем написать метод move_to_res(), который возвращает объект, в который перемещает себя.

Ну, то есть мы сейчас можем написать { return std::move(*this); }
Но для этого нам надо писать конструктор перемещения и всё такое. Напрямую мы такую функцию написать не можем.

Что касается критики идеи с методом move у вектора, то код
std::vector<T> dst;
src.move_to( dst )
ничем особо не хуже метода
std::vector<T> dst = std::move( src );
кроме того, что первое сразу понятно, а второе надо знать пр std::move, конструкторы перемещения и т. д...

Мало того, про метод move_to понятно что он делает, что делает конструктор перемещения коллекции понятно намного меньше.
Например, если посмотрим на std::basic_string<MyType>
Вполне легальна реализация std::basic_string, при которой не очень длинные строки лежат в буфере в самом объекте.
Вот конструктор перемещения такого состояния std::basic_string<MyType> должен звать конструкторы перемещения MyType или нет?
По уму если, должен, но зовёт ли?
И таких тонких мест -- куча ;(
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[11]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 22.11.18 08:15
Оценка:
Здравствуйте, B0FEE664, Вы писали:


BFE>std::string strResult = str1 + str2 + str3 + fun4(); // какая здесь проблема?

А зачем тут что-то, кроме RVO? Это всё и до move-семантики прекрасно работало...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 22.11.18 08:17
Оценка:
Здравствуйте, ViTech, Вы писали:

VT>То, что при этом перемещение может и не произойти, то тут скорее будет вина принимающей стороны, а не функции move.



Я бы как-то move_ready назвал бы...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[18]: Есть ли жизнь после перемещения?
От: ViTech  
Дата: 22.11.18 08:27
Оценка:
Здравствуйте, Пирожочек, Вы писали:

П>вот что дедушка пишет по этому поводу


move(x) means 'give me an rvalue reference to x.' That is, std::move(x) does not move anything; instead, it allows a user to move x. It would have been better if move() had been called rval(), but the name move() has been used for this operation for years


П>и я с ним полностью согласен. move ничего не мувает, а всего лишь кастит к rvalue-ссылке, поэтому название у функции не совсем корректно.


Раз дедушка высказался, хорошо бы узнать, что сказала бы бабушка. Наверное, предложила бы вместо forward() писать fref() . Заманчивая перспектива в программе вместо нормальных слов видеть набор заклинаний.
Пока сам не сделаешь...
Re[12]: Есть ли жизнь после перемещения?
От: Videoman Россия https://hts.tv/
Дата: 22.11.18 08:32
Оценка:
Здравствуйте, Erop, Вы писали:

E>Так что и дальше можно обсуждать механизмы по управлению RVO...


Ну вот приведи разумный пример, когда RVO не нужна?

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


У меня ничего не расползается. Я давно на С++ и кодовая база у меня есть 10-ти летняя, большая, которая компилируется современным компилятором и работает. Ни разу проблем с move я там не встречал.

E>Даже это утверждение неверное, к сожалению. Я знаю примеры, когда дефолтный конструктор копии работает корректно, а дефолтный конструктор перемещения -- нет. Причём молча с очень отдалёнными последствиями.


Я вполне допускаю что такое может быть, иначе бы не было возможности определять/разрешать/запрещать copy/move по отдельности, но это говорит лишь о том, что либо у тебя очень специфический код, либо ты ходишь по тонкому льду вовсю используешь хаки и UB. В общем тут без маленького примера трудно судить.

E>Ну обычно оптимизация нужна в некоторых относительно редких местах, именно в них при случае контроль мог бы пригодиться. В остальных можно не делать ничего. Это, кстати, тоже не соответствует тому, как ввели move-семантику


По мне, так move ввели почти идеально и безболезненно, насколько это было возможно не поломав совместимость.

E>Я не предлагаю решение, я просто показываю, что то как сделали является вовсе не единственной альтернативой. На моё взгляд главная проблема, которую чинил move-конструктор -- это кривой дизайн std::vector со товарищи...

E>При этом его так и не выпрямили

Ну это все точно вкусовщина. Мне, например, вообще не очень нравится STL из-за концепции итераторов. Ты постоянно вынужден следить за их валидностью, за совместимостью, что бы один указывал перед другим и т.д. Получается адское дублирование кода. В элементарных операциях просто безумное количество параметров.
Re[14]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 22.11.18 08:55
Оценка:
Здравствуйте, Erop, Вы писали:

E>Что касается критики идеи с методом move у вектора, то код
std::vector<T> dst;
E>src.move_to( dst )
ничем особо не хуже метода
std::vector<T> dst = std::move( src );
кроме того, что первое сразу понятно, а второе надо знать пр std::move, конструкторы перемещения и т. д...


Вероятно, у нас разные критерии оценки. По-моему, этот код СИЛЬНО хуже:

1) Обязывает предоставлять дефолтный конструктор, что не всегда приемлемо;
2) Вводит необоснованные ограничения на использование ссылок и констант в качестве членов классов;
3) Содержит оверхед на создание никому ненужного состояния объекта;
4) Реализуется с использованием функции-члена, что противоречит принципам обобщенного программированя;
5) Резервирует имя функции-члена, создвавая предпосылки для конфликтов имен;
6) Плохо подходит для работы с разными типами данных. Как только src и dst станут иметь разные тут же выяснится, что в каких-то случаях удобнее иметь "move_to", а каких-то "move_from";
7) Не подходит для автоматической генерации компилятором. Пониммаю, что для тебя это плюс, но не разделяю твою точку зрения. Потому, что сейчас поддержка move семантики в большинстве случаев либо генерируется автоматически, либо сводится к тривиальному разрешить/запретить. В твоем же варианте реально нужно будет все это писать. Раздувая объем кода и натягивая массу ошибок;
8) Вынуждает заводить лишние локальные переменные, что крайне плохо сказывается на структуре кода.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 22.11.2018 9:11 rg45 . Предыдущая версия . Еще …
Отредактировано 22.11.2018 8:58 rg45 . Предыдущая версия .
Re[14]: Есть ли жизнь после перемещения?
От: Videoman Россия https://hts.tv/
Дата: 22.11.18 09:02
Оценка:
Здравствуйте, Erop, Вы писали:

E>...


Не ну критиковать легко конечно, но давай посмотрим что ты предлагаешь и какой синтаксис:
Ты предлагаешь, грубо говоря, src.move(dst);

Т.е. dst уже ложен быть на момент создания. А как через такой синтаксис выразить:
SomeClass b = ....
//...
SomeClass a = b + SomeClass(...); // такое?

SomeClass a = ....
func(std::move(a)); // такое?


А что делать если нам не повезло и у dst нет конструктора по умолчанию? И src у тебя превращается в такое же зомби с неопределенным состоянием. Так чем же твой подход лучше?
Re[12]: Есть ли жизнь после перемещения?
От: B0FEE664  
Дата: 22.11.18 09:14
Оценка:
Здравствуйте, Erop, Вы писали:

BFE>>std::string strResult = str1 + str2 + str3 + fun4(); // какая здесь проблема?

E>А зачем тут что-то, кроме RVO? Это всё и до move-семантики прекрасно работало...

Причём тут RVO? Или это вы так copy elision называете?
И каждый день — без права на ошибку...
Re[14]: Есть ли жизнь после перемещения?
От: B0FEE664  
Дата: 22.11.18 09:37
Оценка:
Здравствуйте, Erop, Вы писали:

E>То, что у нас, как программистов на С++ нет механизмов для прямого написания похожих функций, ну, например, мы не можем написать метод move_to_res(), который возвращает объект, в который перемещает себя.

E>Ну, то есть мы сейчас можем написать { return std::move(*this); }
E>Но для этого нам надо писать конструктор перемещения и всё такое. Напрямую мы такую функцию написать не можем.
Можем:
#include <memory>
#include <iostream>
using namespace std;

class A
{
public:
  A(){}
  A(A&&)=delete;
  A&& move_me(){return std::move(*this); }
};

int main() {
    
  A a;
    
  A&& rrA = a.move_me();
    
  std::cout << "ok\n";
  return 0;
}



E>Что касается критики идеи с методом move у вектора, то код
std::vector<T> dst;
E>src.move_to( dst )
ничем особо не хуже метода
std::vector<T> dst = std::move( src );
кроме того, что первое сразу понятно, а второе надо знать пр std::move, конструкторы перемещения и т. д...

А как быть, если dst — аргумент функции?
И каждый день — без права на ошибку...
Re[8]: Есть ли жизнь после перемещения?
От: ViTech  
Дата: 22.11.18 09:38
Оценка: +1
Здравствуйте, andyp, Вы писали:

A> Видел. Не очень-то с ними разбираются. Просто действуют, предполагая, что худший сценарий возможен, выдавая диагностику, если указатель провис в хотя бы одной из веток условия. Для вызова методов возможно перемещенного объекта по логике то же самое наверное предлагается.


Понятно, что чудес ждать не стоит. Но вы сами считаете следующий код корректным?

void test(bool condition)
{
    A a,b;
    if(condition)
    {
        b = std::move(a);    
    }    
    a.doSomething();
}


Я бы не отказался от предупреждений компилятора для случая вызова метода возможно перемещённого объекта(равно как и возможно удалённого). Что вы предлагаете делать в таких ситуациях?
Пока сам не сделаешь...
Re: Есть ли жизнь после перемещения?
От: Кодт Россия  
Дата: 22.11.18 15:24
Оценка: 12 (2) +1
Здравствуйте, rg45, Вы писали:

R>Всем привет!


Всем привет в чатике!

R>Вопрос несколько философский. Правомерно ли делать какие-либо допущения о состоянии объета, в самом общем случае, после того, как его содержимое было перемещено? Разумеется, состояние объекта должно позволять разрушить этот объект, это сомнению не прдвергается. Но достаточно ли этого? Ведь помимо физического тела у объекта есть еще и логическое состояние — его душа, так сказать. Так вот как быть с ней — нужно ли заботиться о том, чтобы после перемещения объект оставался в целостном состоянии с точки зрения логики программы — на тот случай, если кому-то захочется продолжать пользоваться объектом после его перемещения?


Философия есть в том, что у объекта (особенно, у контейнера) есть общая и частная семантика.
Например, пустой и непустой контейнер, нулевой и ненулевой указатель.

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

После точки move мы требования убираем: содержимое (какое бы оно ни было) утилизировано (каким бы способом это ни было сделано).
В твоём случае с регистрацией:

void register(shared_ptr<R> smth);

void init() {
  shared_ptr<R> r(new R);
  shared_ptr<R> shadow = r;
  somehow_setup(*r);
  register(r);  // move подразумевается, но синтаксически не оформлено
  change_something(*r); // а регистратор-то готов к тому, что мы что-то на ходу поменяли?
  // а даже если бы и было настоящее move c обнулением источника, то что?
  change_something(*shadow);
  // а даже если и на чтение: регистратор же может отдать содержимое в распоряжение другого потока...
  read_something(*shadow);
}


То есть, философский вопрос здесь не о теле и душе, а о том, как далеко по ссылкам и указателям можно лазать шаловливыми руками.
Перекуём баги на фичи!
Re[9]: Есть ли жизнь после перемещения?
От: andyp  
Дата: 22.11.18 19:31
Оценка:
Здравствуйте, ViTech, Вы писали:

VT>Я бы не отказался от предупреждений компилятора для случая вызова метода возможно перемещённого объекта(равно как и возможно удалённого). Что вы предлагаете делать в таких ситуациях?



Да я только за на самом деле . Конечно, полезно будет.
Re[11]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 11:09
Оценка:
Здравствуйте, Videoman, Вы писали:

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

В нормальных программах большие контейнеры не копируют без нужды. И не надо забывать про RVO при этом.


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

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

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

Я вижу три группы сценариев:

1) Оптимизация передачи параметров/значений в/из функции.
2) Оптимизация STL-коллекций в сторону поддержки возможности move значений в другую коллекцию и при переаллокации буфера.
3) Всякая мелочёвка со связыванием r-value с неконстантными ссылками

И есть ещё один новый сценарий -- объекты с невозможностью создания копий, но с возможностью эстафетного копирования.

Вот и надо смотреть что и как можно было сделать в каждом из этих 4 сценариев в тех областях, в которых применяется С++, а не пилить универсальный всемогутер с не до конца понятными последствиями применения.

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

V>Например, оптимальная передача параметров в функцию, не зависимо от того какой тип параметра передается.
Ну, то есть, мы хотим написать шаблон функции, в которой мы говорим что-то типа "первый параметр -- это MyType, но ссылка или копия зависит от того, что удобнее вызвать?
Вообще не совсем понятно, что тут означает слово "оптимальная"



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

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

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

V>Все верно.
Ну то есть это синтаксический сахар над след. конструкцией:

void f( void* to_fill )
{
    // тут код, вычисляющий какие-то params
    ::new( to_fill ) ResType( params ) 
}

и верная передача владения объектом между фреймами разных функций?
Почему это нельзя полостью контролировать средствами языка, а не в режиме "иногда не получается"?

E>>

V>Ну С++ не требует от вас использовать move, куда уж прозрачнее . Move нужен тех случаев, где он нужен и приносит выгоду, а также для явного выражения семантики объектов, которые принципиально не копируемые. Теперь, если нужно, это можно выразить явно и компилятор все будет проверять за вас.
Да враньё всё это. Идеологические утверждения не подтверждаемые практикой. Так же как слабая и сильная готовность к исключениям и прочие идеи про бесплатные полуживые объекты.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[8]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 11:14
Оценка:
Здравствуйте, B0FEE664, Вы писали:

E>>Разве вставка не в конец в std::vector сейчас не через цепочку move-конструкторов/присваиваний работает?

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

Я знал, это, тем не менее, не делает move-семантику лучше, с моей точки зрения
На это можно посмотреть иначе. Я вообще считаю, что С++ очень сильно переусложнён и концептуально и синтаксически и по всякому.
И всякое доп. усложнение, особенно концептуальное, ОЧЕНЬ ДОРОГО СТОИТ. Ну и должно дофига всего давать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[13]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 11:28
Оценка:
Здравствуйте, Videoman, Вы писали:

E>>Так что и дальше можно обсуждать механизмы по управлению RVO...

V>Ну вот приведи разумный пример, когда RVO не нужна?
Не понял, что значит "не нужна"?

V>У меня ничего не расползается. Я давно на С++ и кодовая база у меня есть 10-ти летняя, большая, которая компилируется современным компилятором и работает. Ни разу проблем с move я там не встречал.


"Давно" тут не главное, главное -- большой проект, много людей и т. д...

V>Я вполне допускаю что такое может быть, иначе бы не было возможности определять/разрешать/запрещать copy/move по отдельности, но это говорит лишь о том, что либо у тебя очень специфический код, либо ты ходишь по тонкому льду вовсю используешь хаки и UB. В общем тут без маленького примера трудно судить.


Ну я же приводил пример. У тебя есть авторегистрилки и уведомлялки.
Когда ты из них выводишь объекты, которые получают и рассылают эти все уведомления, и потом их копируешь дефолтным конструктором копии, то в момент создания копии весь оригинал ещё существует в виде MDT, и он весь корректно работает и все рассылки уведомлений между его частями тоже. А когда ты перемещаешь конструктором перемещения, то в процессе перемещения какие-то части уже подписаны, а какие-то ещё нет, в результате инварианты вроде "всех уведомили о" могут теряться...
И да, в оригинальном коде, как и в версии с перемещениями, никаких хаков, UB, "тонких льдов" и т. п. Чистая бизнес-логика, простые компактные инструменты и т. д...

V>По мне, так move ввели почти идеально и безболезненно, насколько это было возможно не поломав совместимость.

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

V>Ну это все точно вкусовщина. Мне, например, вообще не очень нравится STL из-за концепции итераторов. Ты постоянно вынужден следить за их валидностью, за совместимостью, что бы один указывал перед другим и т.д. Получается адское дублирование кода. В элементарных операциях просто безумное количество параметров.


Да, STL -- штука весьма кривая. Это правда.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[15]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 11:43
Оценка:
Здравствуйте, rg45, Вы писали:

R>1) Обязывает предоставлять дефолтный конструктор, что не всегда приемлемо;

R>3) Содержит оверхед на создание никому ненужного состояния объекта;
А чем плох конструктор по умолчанию? На мой взгляд плох не такой конструктор, а то, что нужно поддерживать в классе некое выделенное "значение по умолчанию".
Ну так move-конструктор тоже требует поддержать такое значение же?
В этом смысле я вообще не вижу разницы в подходах.
Но если говорить о попытках выпрямить невозможность перемещения содержимого вектора, то плюс такой, что вообще не надо менять язык.

Но если таки менять, то если бы как-то разрешили описывать конструкции вроде RVO, например, то есть я бы сам мог написать функцию, которой можно было бы передать буфер для конструирования там результата, и её потом было бы удобно вызывать, то ты бы мог написать так, как тебе нравится и не вводя конструктор перемещения.

Да, для конструктора перемещения надо ещё, обычно, и парный метод присваивания, кстати. И в месте вызова всегда трудно понять перемещение будет вызвано или копирование.

R>2) Вводит необоснованные ограничения на использование ссылок и констант в качестве членов классов;

Ну это я согласен. В этом месте конструктор перемещения лучше, но оператор присваивания тогда тоже нельзя залудить.

R>4) Реализуется с использованием функции-члена, что противоречит принципам обобщенного программированя;

Конечно же конструктор-копии -- это не функция-член
В любом случае, если мы хотим написать функцию, которая "крадёт" данные из объекта, она должна иметь доступ к private-части класса.

R>5) Резервирует имя функции-члена, создвавая предпосылки для конфликтов имен;

R>6) Плохо подходит для работы с разными типами данных. Как только src и dst станут иметь разные тут же выяснится, что в каких-то случаях удобнее иметь "move_to", а каких-то "move_from";
Так это же означает, что в случае конструктора копии удобный вариант в половине случаев вообще не получится выбрать.
Он вообще всегда имеет только вариант move_from, называемый "перемещающий оператор присваивания"
Кстати, я уже выше писал, что согласен, что просто move плохое название для такого метода. Лучше, конечно move_to/move_from/swap

R>7) Не подходит для автоматической генерации компилятором. Пониммаю, что для тебя это плюс, но не разделяю твою точку зрения. Потому, что сейчас поддержка move семантики в большинстве случаев либо генерируется автоматически, либо сводится к тривиальному разрешить/запретить. В твоем же варианте реально нужно будет все это писать. Раздувая объем кода и натягивая массу ошибок;

Это место я не понял. Ты про то, что в STL-контейнерах Степанов забыл поддержать такую возможность, как move_to, или про что?


R>8) Вынуждает заводить лишние локальные переменные, что крайне плохо сказывается на структуре кода.


Это тоже не понял. Но как переменная (имеющая имя и смысл) портит структуру кода, ни зачем их заводить?

Мы же говорим о таких примерах кода, где RVO невозможен, да?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[16]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 23.11.18 11:45
Оценка:
Здравствуйте, Erop, Вы писали:

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


Плох не конструктор сам по себе, а то, что он становится обязательным. Появляется ограничение там, где его раньше не было. Бывают такие классы, для которых конструкторы по умолчанию лишены смысла, и их поддержка наносит прямой вред.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 23.11.2018 11:49 rg45 . Предыдущая версия .
Re[15]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 11:48
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Т.е. dst уже ложен быть на момент создания. А как через такой синтаксис выразить:

V>
V>SomeClass b = ....
V>//...
V>SomeClass a = b + SomeClass(...); // такое?
V>

Такое прекрасно работало и до move-семантики через RVO и copy elision…


V>
V>SomeClass a = ....
V>func(std::move(a)); // такое?
V>

Такой, на мой вкус, вообще сомнительно. Смотри, например, вопрос о том, с чего началась эта ветка...

V>А что делать если нам не повезло и у dst нет конструктора по умолчанию? И src у тебя превращается в такое же зомби с неопределенным состоянием. Так чем же твой подход лучше?

Тем, что не надо усложнять язык...
Хуже то, что в этом раскладе move-семантика ничем не лучше, но сложнее

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

Но я в плоском режиме читаю, могу подветки спутать...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Отредактировано 23.11.2018 12:38 Erop . Предыдущая версия . Еще …
Отредактировано 23.11.2018 12:33 Erop . Предыдущая версия .
Re[13]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 11:50
Оценка:
Здравствуйте, B0FEE664, Вы писали:

BFE>Причём тут RVO? Или это вы так copy elision называете?


Ну всю группу таких оптимизаций. RVO, NRVO, copy elision и т. д...
В С++ часто бывает так, что мы вместо того, что бы несколько раз копировать созданный объект, сразу создаём его в нужном месте.

Но формально там среди нескольких конструкторов была и функция ну и operator + у класса тоже как бы функция или метод


p. s.
Тут вроде на "ты" обращение принято?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Отредактировано 23.11.2018 12:36 Erop . Предыдущая версия . Еще …
Отредактировано 23.11.2018 12:34 Erop . Предыдущая версия .
Re[15]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 12:03
Оценка:
Здравствуйте, B0FEE664, Вы писали:

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


E>>То, что у нас, как программистов на С++ нет механизмов для прямого написания похожих функций, ну, например, мы не можем написать метод move_to_res(), который возвращает объект, в который перемещает себя.

E>>Ну, то есть мы сейчас можем написать { return std::move(*this); }
E>>Но для этого нам надо писать конструктор перемещения и всё такое. Напрямую мы такую функцию написать не можем.
BFE>Можем:
Во-первых, этот код вовсе не перемещает себя в результат, он просто возвращает хитрую ссылку на себя же:
Я заменил печать на
  std::cout << "&  a" <<   &a << " -- ok\n";
  std::cout << "&rrA" << &rrA << " -- ok\n";
и ожидаемо получил
&  a0x7fff2679d2ff -- ok
&rrA0x7fff2679d2ff -- ok


Смотри: https://www.ideone.com/0kG6yM

Во-вторых, это вовсе и не "напрямую"...
Напрямую было бы, например, если бы я передавал в функцию адрес (или как-то внутри функции мог бы его получить) того места, где ловят результат снаружи.
Как с this в конструкторах сделано, например...
Кстати, при таком подходе можно было бы возвращать сразу несколько результатов.

E>>Что касается критики идеи с методом move у вектора, то код
std::vector<T> dst;
E>>src.move_to( dst )
ничем особо не хуже метода
std::vector<T> dst = std::move( src );
кроме того, что первое сразу понятно, а второе надо знать пр std::move, конструкторы перемещения и т. д...

BFE>А как быть, если dst — аргумент функции?
А что от этого меняется? Ты правда пытаешься оспорть то, что в контейнерах можно было поддержать возможность move чисто сресдствами библиотеки, не меняя языка?
И это при живых методе и функции swap?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[17]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 12:12
Оценка:
Здравствуйте, rg45, Вы писали:

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



Так конструктор перемещения плох примерно тем же жеж?

Мне, на самом деле, вообще концепция перегруженных конструкторов не особо нравится. Так как функция одинаково называется/вызывается, а делать может разное. Это противоречит обычной практике перегрузки функций...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[18]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 23.11.18 12:25
Оценка:
Здравствуйте, Erop, Вы писали:

E>Так конструктор перемещения плох примерно тем же жеж?


С чего вдруг? У конструктора такие же возможности по инициализации любых членов-данных, в т.ч. ссылок и констант, как и у любого другого конструктора. Только, в отличие от конструктора по умолчанию, у него есть входные данные для такй инициализации.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[19]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 12:35
Оценка:
Здравствуйте, rg45, Вы писали:

R>С чего вдруг? У конструктора такие же возможности по инициализации любых членов-данных, в т.ч. ссылок и констант, как и у любого другого конструктора. Только, в отличие от конструктора по умолчанию, у него есть входные данные для такй инициализации.


С того, что он должен оставить "зомби" на старом месте? Или там пофиг чем константы/ссылки инициализированы? Например ссылки на несуществующие объекты -- это нормально?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[20]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 23.11.18 12:45
Оценка:
Здравствуйте, Erop, Вы писали:

E>С того, что он должен оставить "зомби" на старом месте? Или там пофиг чем константы/ссылки инициализированы? Например ссылки на несуществующие объекты -- это нормально?


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

E>>>Так что и дальше можно обсуждать механизмы по управлению RVO...

V>>Ну вот приведи разумный пример, когда RVO не нужна?
E>Не понял, что значит "не нужна"?

Ну ты хочешь зачем-то управлять RVO. RVO применяется всегда, когда это возможно — значит ты хочешь RVO отключать

E>Ну я же приводил пример. У тебя есть авторегистрилки и уведомлялки.

E>Когда ты из них выводишь объекты, которые получают и рассылают эти все уведомления, и потом их копируешь дефолтным конструктором копии, то в момент создания копии весь оригинал ещё существует в виде MDT, и он весь корректно работает и все рассылки уведомлений между его частями тоже. А когда ты перемещаешь конструктором перемещения, то в процессе перемещения какие-то части уже подписаны, а какие-то ещё нет, в результате инварианты вроде "всех уведомили о" могут теряться...

Не, ну тут у тебя явно ошибка в логике. Ты где-то перемещаешь "душу", а this у тебя где-то старый зависает. Это не относится только к move-у. Совет, используй в таких случаях Impl и всю подписку делай в нем, тогда таких проблем не будет, т.к. он мувается на ура.

E>Я понял в чём суть разногласий. Ты считаешь, что move-семантику ввели практически за бесплатно, а я считаю, что усложнили и весьма заметно, язык.


Да, видимо так. Но все у меня все стало хорошо, как только я перестал переть против "паровоза", немного вник и стал действовать в русле разработчиков стандарта С++.

E>Да, STL -- штука весьма кривая. Это правда.

Re[21]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 20:12
Оценка:
Здравствуйте, rg45, Вы писали:

R>Не "должен", а "может". Важно, что есть возможность полноценно сконструировать новый объект. А что именно остается на старом месте ни чем регламентировано, это может быть что угодно — от полного копирования, до полной выемки всех данных. Собственно, в этом мой вопрос и заключался — что может, а чего не может оставаться на старом месте после перемещения.



Ну ты же понимаешь, что на старом месте позовут потом деструктор?..

Это как бы единственное ограничение.

Но если оставить что-то такое, с чем потом легко злоупотребить, например ссылку на несуществующий объект, то легко устроить потом нечаянно большой бара-бум, как говорила героиня Миллы Йолович в "Пятом элементе"
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[15]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 23.11.18 20:20
Оценка:
Здравствуйте, Videoman, Вы писали:

V>Ну ты хочешь зачем-то управлять RVO. RVO применяется всегда, когда это возможно — значит ты хочешь RVO отключать

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

Я приводил несколько вариантов возможного управления механизмами вроде RVO тут, в дискуссии, если что.

V>Не, ну тут у тебя явно ошибка в логике. Ты где-то перемещаешь "душу", а this у тебя где-то старый зависает. Это не относится только к move-у. Совет, используй в таких случаях Impl и всю подписку делай в нем, тогда таких проблем не будет, т.к. он мувается на ура.


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

V>Да, видимо так. Но все у меня все стало хорошо, как только я перестал переть против "паровоза", немного вник и стал действовать в русле разработчиков стандарта С++.

Я тоже не "пру против паровоза", хотя в том проекте, где я широко пользовался С++ крайний раз, STL не использовался, по многим причинам

Но мы же тут обсуждали
1) Был задан вопрос, какие требования нынешний С++ накладывает на оставляемый move-конструктором "зомби"
2) И как подветку, я высказал тезис, что сам по себе этот вопрос показывает некоторую концептуальную непроработанность move-семантики
После чего мы стали обсуждать умозрительные соображения, как бы можно было решить те же проблемы, иными путями и что ещё можно было бы сделать похожего.
В этой повестке обсуждать паровоз комитета довольно перпендикулярно теме. Был бы у комитета иной паровоз, можно было бы следовать и за ним тоже...

E>>Да, STL -- штука весьма кривая. Это правда.

V>

Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Есть ли жизнь после перемещения?
От: Evgeny.Panasyuk Россия  
Дата: 24.11.18 07:53
Оценка: 18 (1)
Здравствуйте, rg45, Вы писали:

TSP>>В писании сказано:

TSP>>

TSP>>Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

TSP>>Как я понимаю, в общем случае нужно заботиться о целостности объекта после его перемещения.
R>Ну так вот вопрос о понимании этой самой целостности. Одно дело, целостность для того, чтобы похоронить объект и совсем другое — целостность для того, чтобы продолжать им пользоваться.

Для объектов стандартной библиотеки "valid" означает что им можно продолжать пользоваться. Например вектору легально можно сделать .clear(), или .resize(), .size().

R>Этот вопрос можно сформулировать и по-другому: стоит ли требовать от разработчиков, в самом общем случае, документирования состояния объектов после перемещениея?


Документировать конечно стоит. Причём "документацией" может быть одно предложение на весь проект а-ля "Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state".

R>Или исплользование объектов после перемещения — это зло, с которым нужно бороться?


Нет, не зло если разрешено документацией.

R>Или могут быть варианты?

R>P.S. Понятно, что из любого правила могут быть исключения. Но хотелось бы понимать, все-таки, каково же само правило.

Правило стандартной библиотеки привели выше.
Если в проекте используется такая же конвенция как и в стандартной библиотеке, то для тех типов для которых это не выполняется (т.е. "Unless otherwise specified") — может в Debug режиме добавить в методы assert(this->is_valid()).

Если брать непосредственно технический аспект rvalue references — то думаю даже destructability не является формальным требованием языка, а вызов методов не является формальным запретом.

В большинстве же случаев ожидается как минимум нормальная desctructability и возможность move assignment.
Re[10]: Есть ли жизнь после перемещения?
От: Evgeny.Panasyuk Россия  
Дата: 24.11.18 08:08
Оценка: 9 (1)
Здравствуйте, Erop, Вы писали:

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

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

Начиная с C++11 есть list-initialization:
live demo
struct NonCopyableNonMovable
{
    NonCopyableNonMovable(int, double){}

    NonCopyableNonMovable(NonCopyableNonMovable &&) = delete;
    NonCopyableNonMovable(const NonCopyableNonMovable &) = delete;

    NonCopyableNonMovable &operator=(NonCopyableNonMovable &&) = delete;
    NonCopyableNonMovable &operator=(const NonCopyableNonMovable &) = delete;
};

NonCopyableNonMovable foo()
{
    return {1, .5};
}

int main()
{
    auto &&x = foo();
}


А начиная с C++17 есть гарантированное RVO:
live demo
struct NonCopyableNonMovable
{
    NonCopyableNonMovable(int, double){}

    NonCopyableNonMovable(NonCopyableNonMovable &&) = delete;
    NonCopyableNonMovable(const NonCopyableNonMovable &) = delete;

    NonCopyableNonMovable &operator=(NonCopyableNonMovable &&) = delete;
    NonCopyableNonMovable &operator=(const NonCopyableNonMovable &) = delete;
};

NonCopyableNonMovable foo()
{
    return NonCopyableNonMovable{1, .5};
}

int main()
{
    auto x = foo();
}
Re[11]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 24.11.18 11:31
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>А начиная с C++17 есть гарантированное RVO:

EP>live demo
EP>
EP>NonCopyableNonMovable foo()
EP>{
EP>    return NonCopyableNonMovable{1, .5};
EP>}

EP>int main()
EP>{
EP>    auto x = foo();
EP>}
EP>


Разрыв шаблонов и подрыв устоев какой-то

И что в таком случае должно помешать сделать вот так?:

int main()
{
    NonCopyableNonMovable t{1, .5};
    auto x = std::move(t);
}

Разница ведь между std::move и foo только в том, что std::move возвращает rvalue ссылку, тогда как foo возвращает по значению. Теперь эти случаи будут обрабатываться по разным правилам?
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[12]: Есть ли жизнь после перемещения?
От: Evgeny.Panasyuk Россия  
Дата: 24.11.18 12:39
Оценка:
Здравствуйте, rg45, Вы писали:

R>И что в таком случае должно помешать сделать вот так?:


R>
R>int main()
R>{
R>    NonCopyableNonMovable t{1, .5};
R>    auto x = std::move(t);
R>}
R>


Конкретно в этом примере нужен конструктор перемещения, ибо t всё ещё жив, точнее там в области живы оба объекта.

R>Разница ведь между std::move и foo только в том, что std::move возвращает rvalue ссылку, тогда как foo возвращает по значению.


Вот упрощённый пример:
live demo
struct NonCopyableNonMovable
{
    NonCopyableNonMovable(int, double){}

    NonCopyableNonMovable(NonCopyableNonMovable &&) = delete;
    NonCopyableNonMovable(const NonCopyableNonMovable &) = delete;

    NonCopyableNonMovable &operator=(NonCopyableNonMovable &&) = delete;
    NonCopyableNonMovable &operator=(const NonCopyableNonMovable &) = delete;
};

NonCopyableNonMovable foo();

NonCopyableNonMovable &&bar();

int main()
{
    auto   x = foo(); // C++11: fails to compile | C++17: compiles OK
    auto &&y = foo(); // C++11: compiles OK      | C++17: compiles OK
    auto   z = bar(); // C++11: fails to compile | C++17: fails to compile
    auto &&t = bar(); // C++11: compiles OK      | C++17: compiles OK
}


R>Теперь эти случаи будут обрабатываться по разным правилам?


Теперь при возврате по значению И сохранению по значению компилируется, а раньше нет — ибо теперь возможно гарантированное RVO.
Re[13]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 24.11.18 12:47
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:


EP>Теперь при возврате по значению И сохранению по значению компилируется, а раньше нет — ибо теперь возможно гарантированное RVO.


Принцип я понял. И, безусловно, рад такой возможности. Но меня интересовало, как эти требования будут сформулированы в стандарте. Но вот что-то не находится в драфте 17-го ни "RVO", ни "return value optimization".
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[14]: Есть ли жизнь после перемещения?
От: Evgeny.Panasyuk Россия  
Дата: 24.11.18 13:24
Оценка:
Здравствуйте, rg45, Вы писали:

R>Принцип я понял. И, безусловно, рад такой возможности. Но меня интересовало, как эти требования будут сформулированы в стандарте. Но вот что-то не находится в драфте 17-го ни "RVO", ни "return value optimization".


В стандарте используется термин copy/move elision.
Re[14]: Есть ли жизнь после перемещения?
От: σ  
Дата: 24.11.18 19:15
Оценка:
R>Принцип я понял. И, безусловно, рад такой возможности. Но меня интересовало, как эти требования будут сформулированы в стандарте. Но вот что-то не находится в драфте 17-го ни "RVO", ни "return value optimization".

Да и SFINAE в стандарте не находится. И много чего ещё.
Re[13]: Есть ли жизнь после перемещения?
От: Mystic Artifact  
Дата: 24.11.18 23:33
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Теперь при возврате по значению И сохранению по значению компилируется, а раньше нет — ибо теперь возможно гарантированное RVO.

И за счет чего это достигается? Работает ли это при кросс-модульной не PGO компиляции?
Re[14]: Есть ли жизнь после перемещения?
От: σ  
Дата: 25.11.18 01:04
Оценка: 8 (1)
EP>>Теперь при возврате по значению И сохранению по значению компилируется, а раньше нет — ибо теперь возможно гарантированное RVO.
MA>И за счет чего это достигается?
Не "за счёт чего", а "благодаря чему". "За счёт" это когда в одном месте улучшили ценой ухудшения в другом.

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

Если длинно, то: поменяли определения value-категорий и правила инициализации. Раньше prvalue могло обозначать временный объект,
  Скрытый текст
и было непонятно, почему prvalue тогда не подкласс glvalue, которое по определению denotes an object
а теперь это выражение, которое используется для инициализации объекта, причём объект подаётся "снаружи" (The result of a prvalue is the value that the expression stores into its context.).

MA>Работает ли это при кросс-модульной не PGO компиляции?

Как это может помешать?
Re[11]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 25.11.18 11:22
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Начиная с C++11 есть list-initialization:

А как это относится к обсуждаемой теме?
Это просто ещё один способ сконструировать объект где-то в памяти.
А RVO со товарищи, как и возможность ими управлять, -- это про то, ГДЕ конструировать объект и про передачу владения им между фреймами разных контекстов, а не про как конструировать...


p. s.
Гарантированое RVO -- это шаг в направлении, которое мне нравится
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Отредактировано 25.11.2018 11:30 Erop . Предыдущая версия .
Re[12]: Есть ли жизнь после перемещения?
От: Evgeny.Panasyuk Россия  
Дата: 25.11.18 12:24
Оценка:
Здравствуйте, Erop, Вы писали:

E>>>И в этом случае, кстати, можно было бы не требовать наличие открытого конструктора копии

EP>>Начиная с C++11 есть list-initialization:
E>А как это относится к обсуждаемой теме?
E>Это просто ещё один способ сконструировать объект где-то в памяти.

Так ты внимательней смотри — тип NonCopyableNonMovable, при этом мы возвращаем его из функции (наличие конструктора копирования/перемещения не требуется). До появления return {...}; в C++11 так было сделать нельзя. И для других способов сконструировать объект в C++11 это не работает, только для формы return {...};.
Re: Есть ли жизнь после перемещения?
От: SaZ  
Дата: 27.11.18 13:12
Оценка:
Здравствуйте, rg45, Вы писали:

R>Всем привет!


R>Вопрос несколько философский. Правомерно ли делать какие-либо допущения о состоянии объета, в самом общем случае, после того, как его содержимое было перемещено? Разумеется, состояние объекта должно позволять разрушить этот объект, это сомнению не прдвергается. Но достаточно ли этого? Ведь помимо физического тела у объекта есть еще и логическое состояние — его душа, так сказать. Так вот как быть с ней — нужно ли заботиться о том, чтобы после перемещения объект оставался в целостном состоянии с точки зрения логики программы — на тот случай, если кому-то захочется продолжать пользоваться объектом после его перемещения?


Всем добра. Поделюсь своим мнением.
Если хочется, чтобы всегда оставалась "душа", то в вашем случае вместо move надо делать swap. Например, с объектом, сконструированным по умолчанию.
Re[2]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 27.11.18 13:34
Оценка:
Здравствуйте, SaZ, Вы писали:

SaZ>Всем добра. Поделюсь своим мнением.

SaZ>Если хочется, чтобы всегда оставалась "душа", то в вашем случае вместо move надо делать swap. Например, с объектом, сконструированным по умолчанию.

В данном случае акцент чуть другой. В том-то и дело, что мне НЕ хочется. И интересует меня, чем меня за это будут бить

Подход со swap хорош, когда речь идет о перемещающем операторе присваивания. Для конструктора же это означает, что мы сперва должны сконструировать все поля значениями по умолчанию, и только потом уже позвать swap в теле конструктора. Вот это конструирование полей значениями по умолчанию, в то время, когда у нас есть возможность сразу проинициализировать их нужными значениями, мне очень не нравится.
--
Не можешь достичь желаемого — пожелай достигнутого.
Отредактировано 27.11.2018 16:30 rg45 . Предыдущая версия . Еще …
Отредактировано 27.11.2018 13:47 rg45 . Предыдущая версия .
Re[13]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 27.11.18 20:50
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Так ты внимательней смотри — тип NonCopyableNonMovable, при этом мы возвращаем его из функции (наличие конструктора копирования/перемещения не требуется). До появления return {...}; в C++11 так было сделать нельзя. И для других способов сконструировать объект в C++11 это не работает, только для формы return {...};.




Ну это прикольно, но далеко не RVO. Попробуй, например, вернуть таким образом объект рекурсивно (
NonCopyableNonMovable g(); // не важно как она там внутри устроена, но

NonCopyableNonMovable f()
{
    return g(); // что тут пишем?
}
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Есть ли жизнь после перемещения?
От: SaZ  
Дата: 28.11.18 11:47
Оценка:
Здравствуйте, rg45, Вы писали:

R>Подход со swap хорош, когда речь идет о перемещающем операторе присваивания. Для конструктора же это означает, что мы сперва должны сконструировать все поля значениями по умолчанию, и только потом уже позвать swap в теле конструктора. Вот это конструирование полей значениями по умолчанию, в то время, когда у нас есть возможность сразу проинициализировать их нужными значениями, мне очень не нравится.


Может я что-то не так понял, но вам в любом случае нужно как-то сконструировать объект c валидным состоянием (в смысле заполнить перемещаемый объект валидным состоянием), если вы ходите использовать его после std::move. Но мне кажется, что стоит относится к перемещённым объектам как к непригодным для последующего использования.
Во всяком случае ReSharper мне кидает предупреждения, если я использую перемещённый объект.
Re: Есть ли жизнь после перемещения?
От: andyp  
Дата: 12.12.18 09:58
Оценка: 18 (1) +1
Здравствуйте, rg45, Вы писали:

R>Вопрос несколько философский.


Ну вот, они начали что-то подозревать(с). Ну не может в процессе перемещения из одной вещи получаться две .
https://www.youtube.com/watch?v=xxta6LEn9Hk

Семантика, говорили они...
Re[2]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 12.12.18 11:41
Оценка:
Здравствуйте, andyp, Вы писали:

A>Ну не может в процессе перемещения из одной вещи получаться две .


Вот! Очень хорошо сказал. Концепция плывет.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: Есть ли жизнь после перемещения?
От: Erop Россия  
Дата: 22.12.18 22:46
Оценка:
Здравствуйте, rg45, Вы писали:

A>>Ну не может в процессе перемещения из одной вещи получаться две .


R>Вот! Очень хорошо сказал. Концепция плывет.


Так это врождённый дефект move-семантики же?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[4]: Есть ли жизнь после перемещения?
От: rg45 СССР  
Дата: 23.12.18 09:45
Оценка: +1
Здравствуйте, Erop, Вы писали:

E>Так это врождённый дефект move-семантики же?


Может быть.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[2]: Есть ли жизнь после перемещения?
От: маруд Россия  
Дата: 24.12.18 13:09
Оценка:
Здравствуйте, TimurSPB, Вы писали:

R>>Вопрос несколько философский. Правомерно ли делать какие-либо допущения о состоянии объета, в самом общем случае, после того, как его содержимое было перемещено? Разумеется, состояние объекта должно позволять разрушить этот объект, это сомнению не прдвергается. Но достаточно ли этого? Ведь помимо физического тела у объекта есть еще и логическое состояние — его душа, так сказать. Так вот как быть с ней — нужно ли заботиться о том, чтобы после перемещения объект оставался в целостном состоянии с точки зрения логики программы — на тот случай, если кому-то захочется продолжать пользоваться объектом после его перемещения?

TSP>В писании сказано:
TSP>

TSP>Objects of types defined in the C++ standard library may be moved from (12.8). Move operations may be explicitly specified or implicitly generated. Unless otherwise specified, such moved-from objects shall be placed in a valid but unspecified state.

TSP>Как я понимаю, в общем случае нужно заботиться о целостности объекта после его перемещения.
да уж
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.