Ваша первая версия заставляет меня нервничать, потому что вы на самом деле никогда не вызываете конструктор на this
после вызова this->~MyC()
, поэтому ваш объект следует считать недействительным. Даже если код сразу после того, как все текущие переменные-члены приведут к теоретической достоверности, будет подвержен ошибкам.
Ваш второй вариант выглядит лучше, но он все равно оставляет три места, которые должны обновляться каждый раз, когда кто-то добавляетв этот союз ... и учитывая, что ваше перечисление Kind
имеет 4 значения, а вы показываете только три ... Я думаю, что это произойдет рано или поздно. Опять же, склонны к ошибкам.
Я могу подумать о двух других вариантах:
1)
MyC& operator =(const MyC& other)
{
this->~MyC();
new (this) MyC(other);
}
Использовать существующий конструктор копирования на месте, после использования вашего деструктора "на месте ", чтобы избежать утечек. Немного хакерский, намного чище, не требует дополнительного обслуживания.
Это приводит к тому, что у вас есть только два места, где вам нужно вносить изменения, за счет небольшой эффективности в цепочке. Я считаю, что ремонтопригодность в большинстве случаев важнее эффективности. Какие случаи? Спросите своего профилировщика.
ПРЕДУПРЕЖДЕНИЕ. Как отметил Крис в комментариях ниже, это приведет к ужасным ошибкам при работе с классом, производным от MyC, если только у этого класса нет собственного оператора присваивания. Если бы он вызывался в каком-либо производном классе, этот класс
- пропускал бы все, что требовало вызова деструктора производного класса.
- превращал производный класс в экземпляр MyC. В ОСНОВНОМ. Я подозреваю, что производный деструктор по-прежнему будет вызываться, и за ним может последовать большая опасность
- ОТО, это могло бы просто очистить весь материал, который «просочился», когда мы ранее назвали неправильный деструктор. Это действительно просто зависит.
С одной стороны, этот кодекс является отличным примером ходьбы по высокой веревке без сетки. С другой стороны, так работает с новым / удалить напрямую. У нас просто больше практики, чтобы ходить по этой конкретной веревке, и у нас есть сети, такие как unique_ptr
и shared_ptr
, которые мы можем (и обычно должны) использовать.
2)
Оберните ваш союз в некоторыхлюбой / вариант шаблона (std :: option, boost :: any, что угодно), согласно комментарию Ричарда. У моего последнего работодателя было что-то вроде 3 разных вариантов / любых классов, написанных тремя разными программистами, по крайней мере двое из которых явно не удосужились сначала осмотреть нашу кодовую базу. У вашей компании тоже могут быть свои собственные реализации.
Не думайте, что они будут менее эффективными. Опять же: спросите своего профилировщика.
не имеет отношения: при поиске в кодовой базе бывшего работодателя интересных фраз, таких как «не регистрироваться», ненормативная лексика и т. Д., Были найдены все интересные вещи. Это была игровая компания, поэтому вещи были значительно менее «сдержанными», чем можно было бы найти в другом месте. Это сделано для занимательного чтения.