Могу ли я использовать размещение new (this) в operator =? - PullRequest
9 голосов
/ 24 августа 2011

Справочная информация: У меня сложный класс со многими переменными. У меня есть надежный и проверенный экземпляр конструктора:

Applepie::Applepie( const Applepie &copy) :
m_crust(copy.m_crust),
m_filling(copy.m_filling)
{
}

Некоторые из конструкторов копирования переменных-членов, вызываемых в списке инициализаторов, выполняют распределение.

Вопрос: Мне нужно создать operator=. Вместо того, чтобы дублировать существующий конструктор с присваиванием вместо списка инициализации и освободить заменяемую память, и т. Д. И т. Д., Я могу просто сделать следующее:

Applepie& Applepie::operator=( const Applepie &copy)
{
    if( this != &copy)
    {
       this->~Applepie(); // release own object
       new(this) Applepie(copy); // placement new copy constructor
    }
    return *this;
}

Другими словами, уничтожается ли сам с последующим размещением нового конструктора копирования, семантически идентичного operator =?

Похоже, что это может значительно сократить количество повторяющихся кодов и подтвердить, что каждая переменная инициализирована должным образом, за счет возможной небольшой потери эффективности во время присвоения. Я что-то упускаю из виду?

Обоснование: Мой настоящий класс имеет около 30 переменных. Я обеспокоен тем фактом, что и мой конструктор копирования, и мой оператор присваивания должны копировать все тридцать и что код может расходиться, в результате чего две операции будут действовать по-разному.

Ответы [ 2 ]

6 голосов
/ 24 августа 2011

Как утверждает Херб Саттер в «Исключительном C ++», он не является безопасным для исключения. Это означает, что если что-то идет не так во время new или создания нового объекта, левый операнд присваивания находится в плохом (неопределенном) состоянии, что вызывает дополнительные проблемы. Я настоятельно рекомендую использовать copy & swap idiom .

Applepie& Applepie::operator=(Applepie copy)
{
  swap(m_crust, copy.m_crust);
  swap(m_filling, copy.m_filling);
  return *this;
}

Когда ваш объект также использует идиому Pimpl (указатель на реализацию), обмен выполняется путем изменения только двух указателей.

1 голос
/ 24 августа 2011

В дополнение к ответу Рене существует также проблема того, что произойдет, если ApplePie будет базовым классом реального объекта: ApplePie заменит объект объектом неправильного типа!

...