Это грязный хак, но вы можете уничтожить и восстановить себя:
MyItemT&
MyItemT::operator=(const MyItemT& other)
{
if ( this == &other ) return *this; // "suggested" by Herb Sutter ;v)
this->MyItemT::~MyItemT();
try {
new( this ) MyItemT( other );
} catch ( ... ) {
new( this ) MyItemT(); // nothrow
throw;
}
return *this;
}
Редактировать: чтобы я не разрушил свой авторитет, на самом деле я сам этого не сделаю, я бы удалил const
. Тем не менее, я спорил об изменении практики, потому что const
просто полезен и его лучше использовать везде, где возможно.
Иногда существует различие между ресурсом и значением, представленным объектом. Член может быть подвержен изменениям значения до тех пор, пока ресурс остается тем же, и было бы неплохо обеспечить безопасность во время компиляции.
Редактировать 2: @Charles Bailey предоставил эту замечательную (и очень критическую) ссылку: http://gotw.ca/gotw/023.htm.
- Семантика сложна в любом производном классе
operator=
.
- Это может быть неэффективно, поскольку не вызывает определенные операторы присваивания.
- Он несовместим с перегрузками Wickky
operator&
(что угодно)
- и т.д.
Редактировать 3: Обдумывая разницу между «какой ресурс» и «какое значение», кажется очевидным, что operator=
всегда должно менять значение, а не ресурс. Тогда идентификатор ресурса может быть const
. В этом примере все члены const
. Если «информация» - это то, что хранится внутри «пакета», то, возможно, пакет должен быть const
, а информация - нет.
Таким образом, проблема не столько в выяснении семантики присваивания, сколько в отсутствии очевидного значения в этом примере, если «информация» на самом деле является метаданными. Если какой-либо класс, владеющий MyItemT
, хочет переключить его с одного пакета на другой, ему нужно либо отказаться от использования auto_ptr<MyItemT>
, либо прибегнуть к такому же взлому, как указано выше (проверка идентичности не нужна, но catch
остальное) реализовано извне . Но operator=
не должен изменять привязку ресурса, кроме как сверхспециальная функция, которая абсолютно не мешает ничему другому.
Обратите внимание, что это соглашение хорошо согласуется с рекомендацией Саттера о реализации конструкции копирования с точки зрения назначения.
MyItemT::MyItemT( MyItemT const &in )
: mMyPacket( in.mMyPacket ) // initialize resource, const member
{ *this = in; } // assign value, non-const, via sole assignment method