Информация об изменениях

Сообщение Re: std::move, advanced от 23.11.2015 7:26

Изменено 23.11.2015 7:32 uzhas

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

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;

  1. 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.
  2. Effects: Transfers ownership from u to *this as if by calling reset(u.release()) followed by get_deleter() = std::forward<D>(u.get_deleter()).
  3. Returns: *this.

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

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;

  1. 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.
  2. Effects: Transfers ownership from u to *this as if by calling reset(u.release()) followed by get_deleter() = std::forward<D>(u.get_deleter()).
  3. Returns: *this.