Re[3]: Ссылки и move semantics
От: watchmaker  
Дата: 24.07.15 14:35
Оценка:
Здравствуйте, Videoman, Вы писали:

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

Нет, смысл этого в другом — источник должен остаться в таком состоянии, что его удаление не уронит программу. Если у тебя есть unique_ptr, то в реализации должен изменяться указатель у источника при move — иначе память, на которую будут ссылаться оба указателя, будет освобождена дважды и программа упадёт.
Если другой wrapper_ptr не удаляет память в деструкторе, то указатель можно и не менять — всё будет работать. Если wrapper_ref содержит ссылку — то тем более её нет нужды менять — её «удаление» не уронит программу просто из-за того, что разрушение ссылки в деструкторе — суть отсутствие каких-либо действий.



W>>Но лучше просто следовать правилу «не использовать объект после std::move». Нарушил — сам виноват.

V>Ну.... по-моему это противоречит утверждению, что объект должен оставаться в консистентном состоянии.

В языке C++ есть понятие «implementation-defined behavior» — то есть в каждом конкретном случае поведение определено, но какое оно — зависит от реализации и может меняться.
Тут примерно то же самое — объект остался в консинстентном состоянии, но неизвестно какое это состояние. Так, например, то же перемещение из vector<T> может как сделать объект пустым, так и наполнить его какими-нибудь данными. Оба случая встречаются на практике. В обоих случаях поведение является допустимым, а состояние объекта остаётся согласованным, но вот использовать этот объект просто так не стоит — ведь записав в него через push_back какие-то данные не будет гарантии, что в нём не останется какой-то другой мусор.
Вот именно из-за этого и не стоит использовать объекты после move.

Конечно, это правило не абсолютно — можно ведь просто изучить исходный код и посмотреть что-же там внутри на самом деле происходит. Для переносимых программ и стандартной библиотеки это не вариант, но для собственноручно написанных классов вполне так можно делать. Хотя следуя принципу наименьшего удивления — всё же не стоит.

Да, в примере с vector можно делать ему resize(0) и продолжать использовать дальше. Но тут совсем нет универсального способа сделать это для всех классов. Некоторые объекты просто нельзя переиспользовать.

V>У классов без ссылок я могу переинициализировать члены — я так и делаю.

Ясно, а зачем? Использовал обёртку и выкинул, вместо этого создал другую. Такой вариант тебе не подходит? Ну тогда используй просто указатели вместо ссылок — и вопрос решён.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.