Выполнение функции copy
T
); в этом случае вам придется перехватывать исключение и освобождать связанную с ним память.Вы можете поступить по-другому и копировать объект при помощи оператора присваивания, operator=
Возможно, вам все здесь ясно с первого взгляда, но я дам пояснения на тот случай, если это не так. Рассмотрим первую строку, в которой создается временный объект tmp
Message tmp(rhs);
В данном случае мы просто создали двойника объекта-аргумента. Естественно, теперь tmp
rhs
. После этого мы обмениваем значения его членов со значениями членов объекта *this
.swapInternals(tmp);
Вскоре я вернусь к функции swapInternals
*this
имеют значения, которые имели члены tmp
секунду назад. Однако объект tmp
представлял собой копию объекта rhs
, поэтому теперь *this
эквивалентен rhs
. Но подождите: у нас по-прежнему имеется этот временный объект. Нет проблем, когда вы возвратите *this
, tmp будет автоматически уничтожен вместе со старыми значениями переменных-членов при выходе за диапазон его видимости.return(*this);
Все так. Но обеспечивает ли это безопасность при исключениях? Безопасно конструирование объекта tmp
swapInternals
, поэтому рассмотрим, что в ней делается, и безопасны ли эти действия при исключениях.Функция swapInternals
swap
, которая принимает два аргумента Поскольку объект key_
key_
. Когда вы работаете с членами объекта, все зависит от обеспечения ими гарантий безопасности при исключениях. Если такой член не выбрасывает исключение, то это значит, что я добился своего, так как обмен значений переменных встроенных типов не приведет к выбрасыванию исключений. Следовательно, функция swapInternals
является в основном и строгом смысле безопасной при исключениях.Однако возникает интересный вопрос. Что, если у вас имеется несколько объектов-членов? Если бы вы имели два строковых члена, начало функции swapInternals
void swapInternals(Message& msg) {
swap(key_, msg key_);
swap(myObj_, msg.myObj_);
// ...
Существует одна проблема: если вторая операция swap
swap
? Другими словами, теперь key_
имеет новое значение, но операция swap
для myObj_
завершилась неудачей, поэтому key_
теперь испорчен. Если вызывающая программа перехватывает исключение и попытается продолжить работу, как будто ничего не случилось, она теперь будет обрабатывать нечто отличное от того, что было в начале. Одно из решений — предварительно скопировать key_
во временную строку, но это не гарантирует безопасность, так как при копировании может быть выброшено исключение.Одно из возможных решений состоит в использовании объектов, распределенных в динамической памяти.
void swapInternals(Message& msg) {