Сообщение Re: std::move, advanced от 23.11.2015 7:26
Изменено 23.11.2015 7:32 uzhas
J>Мой вопрос в том, что, к примеру в 1й строке, состояние объекта 'x' вытаскивается и ложится в 'z', оставляя 'x' в некоем состоянии с которым можно только вызвать деструктор, никак более переиспользовать нельзя.
неправильный посыл в логических рассуждениях. вы рассматриваете вариант, когда после перемещения объект не должен переиспользоваться. есть много случаев, когда объект можно переиспользовать для послежних и придумали такой swap
J>Тут же как видно, объекту можно присвоить и потом объект можно будет использовать по полной, как обычно.
J>Я вижу в этом противоречие.
нет противоречий, вы их выдумали
J>User defined типы впринципе необязаны оставаться присваемыми. Т.е. этот своп это чистый undefined behaviour.
да, использование такого swap для таких типов ведет к UB. для других типов такой swap не ведет к UB и работает, как задумано
J>С одной стороны отдавать указатель по std::move — есть самое верное для unique_ptr. Но при этом дальнейшее переиспользование этого же указателя является прямым нарушением стандарта.
для unique_ptr все легально, после move его можно использовать заново (хотя формулировка стандарта все же не так внятна на этот счет)
20.8 Smart pointers [smartptr]
20.8.1 Class template unique_ptr [unique.ptr]
...
4 Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of
such a transfer, the following postconditions hold:
(4.1) — u2.p is equal to the pre-transfer u.p,
(4.2) — u.p is equal to nullptr, and
(4.3) — if the pre-transfer u.d maintained state, such state has been transferred to u2.d.
As in the case of a reset, u2 must properly dispose of its pre-transfer owned object via the pre-transfer
associated deleter before the ownership transfer is considered complete. [ Note: A deleter’s state need never
be copied, only moved or swapped as ownership is transferred. —end note ]
20.8.1.2.3 unique_ptr assignment [unique.ptr.single.asgn]
unique_ptr& operator=(unique_ptr&& u) noexcept;
Requires: If D is not a reference type, D shall satisfy the requirements of MoveAssignable (Table 22)
and assignment of the deleter from an rvalue of type D shall not throw an exception. Otherwise,
D is a reference type; remove_reference_t<D> shall satisfy the CopyAssignable requirements and
assignment of the deleter from an lvalue of type D shall not throw an exception.
Effects: Transfers ownership from u to *this as if by calling reset(u.release()) followed by get_deleter() = std::forward<D>(u.get_deleter()).
Returns: *this.
J>Мой вопрос в том, что, к примеру в 1й строке, состояние объекта 'x' вытаскивается и ложится в 'z', оставляя 'x' в некоем состоянии с которым можно только вызвать деструктор, никак более переиспользовать нельзя.
неправильный посыл в логических рассуждениях. вы рассматриваете вариант, когда после перемещения объект не должен переиспользоваться. есть много случаев, когда объект можно переиспользовать для последних и придумали такой swap
J>Тут же как видно, объекту можно присвоить и потом объект можно будет использовать по полной, как обычно.
J>Я вижу в этом противоречие.
нет противоречий, вы их выдумали
J>User defined типы впринципе необязаны оставаться присваемыми. Т.е. этот своп это чистый undefined behaviour.
да, использование такого swap для таких типов ведет к UB. для других типов такой swap не ведет к UB и работает, как задумано
J>С одной стороны отдавать указатель по std::move — есть самое верное для unique_ptr. Но при этом дальнейшее переиспользование этого же указателя является прямым нарушением стандарта.
для unique_ptr все легально, после move его можно использовать заново (хотя формулировка стандарта все же не так внятна на этот счет)
20.8 Smart pointers [smartptr]
20.8.1 Class template unique_ptr [unique.ptr]
...
4 Additionally, u can, upon request, transfer ownership to another unique pointer u2. Upon completion of
such a transfer, the following postconditions hold:
(4.1) — u2.p is equal to the pre-transfer u.p,
(4.2) — u.p is equal to nullptr, and
(4.3) — if the pre-transfer u.d maintained state, such state has been transferred to u2.d.
As in the case of a reset, u2 must properly dispose of its pre-transfer owned object via the pre-transfer
associated deleter before the ownership transfer is considered complete. [ Note: A deleter’s state need never
be copied, only moved or swapped as ownership is transferred. —end note ]
20.8.1.2.3 unique_ptr assignment [unique.ptr.single.asgn]
unique_ptr& operator=(unique_ptr&& u) noexcept;
Requires: If D is not a reference type, D shall satisfy the requirements of MoveAssignable (Table 22)
and assignment of the deleter from an rvalue of type D shall not throw an exception. Otherwise,
D is a reference type; remove_reference_t<D> shall satisfy the CopyAssignable requirements and
assignment of the deleter from an lvalue of type D shall not throw an exception.
Effects: Transfers ownership from u to *this as if by calling reset(u.release()) followed by get_deleter() = std::forward<D>(u.get_deleter()).
Returns: *this.