Стандарты программирования на С++. 101 правило и рекомендация | страница 97
>T& T::operator=(const T& other) { // Вариант 1 (традиционный)
> T temp(other);
> swap(temp);
> return *this;
>}
>T& T::operator=(T temp) { // Вариант 2 (см. рекомендацию 27)
> swap(temp); // Обратите внимание на передачу
> return *this; // temp по значению
>}
Но что если тип >U
не имеет бессбойной функции обмена, как в случае многих существующих классов, но вам требуется поддержка функции обмена для типа >T
? Не все потеряно.
• Если копирующий конструктор и оператор копирующего присваивания >U
не дают сбоев, то с объектами типа >U
вполне справится >std::swap
.
• Если копирующий конструктор >U
может давать сбой, вы можете хранить (интеллектуальный) указатель на >U
вместо непосредственного члена. Указатели легко обмениваются. Следствием их применения являются дополнительные расходы на одно динамическое выделение памяти и дополнительную косвенность при обращении, но если вы храните все такие члены в едином Pimpl-объекте, то для всех закрытых членов дополнительные расходы вы понесете только один раз (см. рекомендацию 43).
Никогда не пользуйтесь трюком реализации копирующего присваивания посредством копирующего конструирования с использованием непосредственного вызова деструктора и размещающего new, несмотря на то, что такой трюк регулярно "всплывает" в форумах, посвященных С++ (см. также рекомендацию 99). Так что никогда не пишите:
>T& T::operator=(const T& rhs) { // Плохо: анти-идиома
> if (this != &rhs) {
> this->~T(); // плохая методика!
> new(this) T(rhs); // (см. [Sutter00] §41)
> }
> return *this;
>}
Если объекты вашего типа можно обменять более эффективным способом, чем грубое присваивание, желательно предоставить функцию обмена, не являющуюся членом, в том же пространстве имен, где находится и ваш тип (см. рекомендацию 57). Кроме того, подумайте о специализации >std::swap
для ваших собственных нешаблонных типов:
>namespace std {
>template<> void swap(MyType& lhs, MyType& rhs) {
> lhs.swap(rhs); // Для объектов MyType используется
>} // MyType::swap
>}
Стандарт не позволяет вам сделать это, если >MyType
сам является шаблонным классом. К счастью, иметь такую специализацию хорошо, но не обязательно; основная методика состоит в обеспечении функции