For example, stdlibc++ has the following:
unique_lock& operator=(unique_lock&& __u)
{
if(_M_owns)
unlock();
unique_lock(std::move
I will answer the question from header: "Why do some people use swap for move assignments?".
The primary reason to use swap is providing noexcept move assignment.
From Howard Hinnant's comment:
In general a move assignment operator should:
1. Destroy visible resources (though maybe save implementation detail resources).
But in general destroy/release function can fail and throw exception!
Here is an example:
class unix_fd
{
int fd;
public:
explicit unix_fd(int f = -1) : fd(f) {}
~unix_fd()
{
if(fd == -1) return;
if(::close(fd)) /* !!! call is failed! But we can't throw from destructor so just silently ignore....*/;
}
void close() // Our release-function
{
if(::close(fd)) throw system_error_with_errno_code;
}
};
Now let's compare two implementaions of move-assignment:
// #1
void unix_fd::operator=(unix_fd &&o) // Can't be noexcept
{
if(&o != this)
{
close(); // !!! Can throw here
fd = o.fd;
o.fd = -1;
}
return *this;
}
and
// #2
void unix_fd::operator=(unix_fd &&o) noexcept
{
std::swap(fd, o.fd);
return *this;
}
#2 is perfectly noexcept!
Yes, close() call can be "delayed" in case #2. But! If we want strict error checking we must use explicit close() call, not destructor. Destructor releases resource only in "emergency" situations, where exeption can't be thrown anyway.
P.S. See also discussion here in comments