I was investigating the performance of moving std::string
. For the longest time, I've regarded string moves as almost free, thinking the compiler will inline everything and it will only involve a few cheap assignments.
In fact, my mental model for moving is literally
string& operator=(string&& rhs) noexcept
{
swap(*this, rhs);
return *this;
}
friend void swap(string& x, string& y) noexcept
{
// for disposition only
unsigned char buf[sizeof(string)];
memcpy(buf, &x, sizeof(string));
memcpy(&x, &y, sizeof(string));
memcpy(&y, buf, sizeof(string));
}
To the best of my understanding, this is a legal implementation if the memcpy
is changed to assigning individual fields.
It is to my great surprise to find gcc's implementation of moving involves creating a new string and might possibly throw due to the allocations despite being noexcept
.
Is this even conforming? Equally important, should I not think moving is almost free?
Bewilderingly, std::vector<char>
compiles down to what I'd expect.
clang's implementation is much different, although there is a suspicious std::string::reserve