c++ - Is std::swap(x, x) guaranteed to leave x unchanged? -


this question based on discussion below recent blog post scott meyers.

it seems "obvious" std::swap(x, x) should leave x unchanged in both c++98 , c++11, can't find guarantee effect in either standard. c++98 defines std::swap in terms of copy construction , copy assignment, while c++11 defines in terms of move construction , move assignment, , seems relevant, because in c++11 (and c++14), 17.6.4.9 says move-assignment need not self-assignment-safe:

if function argument binds rvalue reference parameter, implementation may assume parameter unique reference argument. ... [ note: if program casts lvalue xvalue while passing lvalue library function (e.g. calling function argument move(x)), program asking function treat lvalue temporary. implementation free optimize away aliasing checks might needed if argument lvalue. —end note ]

the defect report gave rise wording makes consequence clear:

this clarifies move assignment operators need not perform traditional if (this != &rhs) test commonly found (and needed) in copy assignment operators.

but in c++11 , c++14, std::swap expected use implementation,

template<typename t> void swap(t& lhs, t& rhs) {   auto temp(std::move(lhs));   lhs = std::move(rhs);   rhs = std::move(temp);  } 

and first assignment performing assignment self argument rvalue. if move assignment operator t follows policy of standard library , doesn't worry assignment self, seem court undefined behavior, , mean std::swap(x, x) have ub, well.

that's worrisome in isolation, if assume std::swap(x, x) supposed safe in c++98, means c++11/14's std::swap silently break c++98 code.

so std::swap(x, x) guaranteed leave x unchanged? in c++98? in c++11? if is, how interact 17.6.4.9's permission move-assignment not self-assignment-safe?

your assumption c++11/14 std::swap implementation wrong. in version temp being copy constructed 1 of arguments; however, there's no need this. temp can move constructed, , rest remains same example

template<typename t> void swap(t& lhs, t& rhs) // omitting noexcept specification {   t temp = std::move(lhs);   lhs = std::move(rhs);   rhs = std::move(temp);  } 

the second statement still self-move-assignment, resource owned lhs (and rhs) has been moved temp. both objects should in "valid unspecified" state, , assignment shouldn't cause trouble @ point.

edit: found this answer howard hinnant discusses situation (about 2/3rds of way down). assessment same above.


Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

Python ctypes access violation with const pointer arguments -