Вместо двух свопов я хочу реализовать одну замену 16 байт MyString.
Код: Выделить всё
class MyString {
std::size_t size_;
char* str_;
MyString(const char* str, std::size_t len): size_(len), str_(size_ ? new char[size_+1] : nullptr) {
if (size_) {
memcpy(str_, str, len+1);
}
}
void bitwise_swap(MyString* l, MyString* r) {
constexpr size_t size = sizeof(MyString);
alignas (MyString) char tmp[size]; // is alignas even necessary?
std::memcpy(&tmp, l, size);
std::memcpy(l, r, size);
std::memcpy(r, &tmp, size);
}
public:
MyString(const char* str = ""): MyString(str, strlen(str)) {
}
MyString(MyString&& s) noexcept : size_(0), str_(nullptr) {
bitwise_swap(this, &s);
}
MyString& operator=(MyString&& s) {
bitwise_swap(this, &s);
return *this;
}
~MyString() {
delete[] str_;
}
};
Кроме того, меня устраивает замена оператора = на его параметр. Если получено xvalue (т. е. lvalue, которое было std::moved, меня устраивает, что оно несет мой «мусор»). Итак, сравните с этими версиями:
Код: Выделить всё
MyString(MyString&& s) noexcept : size_(0), str_(nullptr) {
std::swap(size_, s.size_);
std::swap(str_, s.str_);
}
Код: Выделить всё
MyString& operator=(MyString&& s) {
std::swap(size_, s.size_);
std::swap(str_, s.str_);
return *this;
}
Некоторые (справедливо) скажут, что это преждевременная оптимизация, но может ли кто-нибудь утверждать, что одна версия обычно более эффективна, чем другая, или что типичные компиляторы обычно сами выполняют такую оптимизацию? т.е. превратите два свопа по 8 байт в один своп по 16 байт.
Подробнее здесь: https://stackoverflow.com/questions/792 ... r-mystring