0

У меня есть вопрос о назначении оператора при использовании метода copy-and-swap.Почему мы используем копирование и свопинг при использовании оператора присваивания?

String & operator = (String s) // the pass-by-value parameter serves as a temporary 
{ 
    s.swap (*this); // Non-throwing swap 
    return *this; 
}// Old resources released when destructor of s is called. 

Предположим, у нас есть хороший конструктор копирования, который глубоко копирует все указатели и динамические распределенные переменные.

Тогда какая разница между приведенным выше кодом и ниже кодом?

String & operator = (String s) // the pass-by-value parameter serves as a temporary 
{ 
    return s; 
} 

Так, у нас есть хороший конструктор копирования, я думаю, еще один объект, s, создается внутри оператора = функции. Итак, в чем смысл использования функции неперебрасывания swap?

ответ

3

Основное отличие состоит в том, что второй operator= не изменяет текущий объект (то есть *this) вообще.

String a, b; 
b = a; // b is not changed at all 

И обратите внимание на второй operator= возвращается s (который будет уничтожен, когда выйти из функции) по ссылке, так что это будет просто болтался ссылки.


Чтобы быть более общим, мы используем copy & swap idiom, чтобы обеспечить надежную гарантию безопасности исключение, которое является чем-то вроде фиксации или отката-семантики; Если операция прекращается из-за исключения, состояние программы останется неизменным.

String & operator = (String s) // Copy construct s. If exception happens here, 
           // s won't be constructed, 
           // and the state of the current object (*this) won't be changed 
{ 
    s.swap (*this);    // Use non-throwing swap to commit the change 
    return *this;    // Non-throwing operation 
} 
+0

Oh! Ответ был таким простым. Спасибо :) – kong0329

+0

@ kong0329 Я не на 100% уверен, что это ваш реальный вопрос. В любом случае, я добавил дополнительную информацию об идиоме копирования и свопа, надеюсь, помогает. – songyuanyao

+0

Это очень помогло мне. Теперь я получил смысл использовать идиому copy & swap! – kong0329

0

Разница заключается в том, что в вашем втором кодовом блоке вы создаете копию s объекта String, возвращаете ссылку на него, а затем копия разрушается при выходе из области действия, что приводит к тому, что ваша программа имеет неопределенное поведение.

0

Есть несколько основных отличий:

Оператор присваивания должен возвращать *this (и почти всегда делает). Это то, что делает назначение цепочки возможным.

String s1, s2, s3; 
s1 = s2 = s3; // Now all strings ave the same value. 

Вместо этого вы возвращаете ссылку на локальную переменную. Затем он становится связующим звеном, поскольку он не указывает на допустимую ячейку памяти.

Кроме того, оператор присваивания должен изменить назначенный объект, чего не происходит в коде.

И, наконец, зачем нам вообще не нужна замена? Предположим, что ваш оператор присваивает исключение. Каково состояние назначенного объекта после неудачного назначения?

Некоторые реализации могут привести к тому, что объект окажется в недопустимом состоянии, поскольку исключение было выбрано в середине его изменения.

Здесь происходит своп. Поскольку своп никогда не срабатывает, мы можем быть уверены, что назначенный объект находится в допустимом состоянии. Если перед свопом выбрано исключение, объект все еще имеет свое старое значение, и если бы это было после обмена, у объекта было новое значение.

+0

Назначение не обязано * возвращать '* этот'. Это просто странное соглашение, которое мы собрали на этом пути. – Barry