Я реализую идиому копирования и свопинга для operator=
небольшого объекта, не связанного с владением памятью, который я разработал. Когда MemRef
ссылается на кусок буфера, чье жизненное время я доверяю, _ptr
указывает на буфер, как и следовало ожидать.
Что необычно в этом MemRef
заключается в том, что он состоит не только из _ptr
и a _len
, но также и _memory
std::string
: есть определенные пользователи (или ситуации) этого класса, Я не верю, чтобы защитить их память; для них я фактически копирую свою память в строку _memory
во время построения и устанавливаю _ptr = _memory.c_str()
. Я всегда могу определить, есть ли у меня "inref" MemRef (ссылаясь на его внутреннюю память) или "exref" MemRef (ссылаясь на некоторый внешний буфер), спрашивая, есть ли _ptr == _memory.c_str()
.
Я смущен тем, как писать процедуру подкачки. Из идиомы копирования и свопинга взято следующее:
Здесь operator=
:
MemRef&
MemRef::operator=(MemRef other) {
swap(*this, other);
return *this;
}
Здесь конструктор копирования:
// Copy ctor
MemRef::MemRef(const MemRef& other) :
_memory(other._memory),
_ptr(other._ptr),
_len(other._len)
{ // Special provision if copying an "inref" MemRef
if (other._ptr == other._memory.c_str()) {
_ptr = _memory.c_str();
}
}
И вот мой swap(first, second)
- который, мне кажется, требует больше работы.
void
swap(MemRef& first, MemRef& second) {
using std::swap;
swap(first._memory, second._memory);
swap(first._ptr, second._ptr);
swap(first._len, second._len);
}
Итак, если у меня есть:
MemRef mr_a("foo"); // creates an "inref" memref
MemRef mr_b(buffer_ptr, length); // creates an "exref" memref -> "blarch"
mr_a = mr_b;
operator=()
вызывается с временным MemRef, созданным копированием mr_b; он вызывает swap(mr_a, mr_b_copy);
swap()
обменивает указатель, длину и строку (так что прежнее содержимое mr_a будет разрушено вместе с mr_b_copy).
Я не понимаю, являются ли указатели в mr_a и mr_b_copy правильными в этой точке, или если они запутались друг с другом.
ОБНОВЛЕНИЕ 1. Приведенный выше пример не иллюстрирует проблему. Рассмотрим это:
MemRef mr_a; // creates a memref with _ptr(NULL), _len(0)
mr_a = "woof"; //
Для передачи по значению оператору =() временный inref создается для "woof" и привязан к параметру other
. Затем ссылки на mr_a
и other
передаются в swap() и связаны как first
и second
соответственно. После обмена, first._ptr
был... ну, неправильно. Указывает на мусор. Вот что я должен был сделать:
void
swap(MemRef& first, MemRef& second) {
using std::swap;
// second is an exref
if (second._ptr != second._memory.c_str()) {
swap(first._memory, second._memory);
swap(first._len, second._len);
swap(first._ptr, second._ptr);
}
// second is an inref
else {
swap(first._memory, second._memory);
swap(first._len, second._len);
first._ptr = first._memory.c_str();
}
}
Я могу заключить, что std:: swap (string, string) делает что-то странное.