Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π‘Ρ‚Π°Π½Π΄Π°Ρ€Ρ‚Ρ‹ программирования Π½Π° Π‘++. 101 ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ ΠΈ рСкомСндация». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 30

Автор Π“Π΅Ρ€Π± Π‘Π°Ρ‚Ρ‚Π΅Ρ€

// ОбъявляСм ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ конструктор ΠΊΠ°ΠΊ explicit (Ρƒ Π΄Π°Π½Π½ΠΎΠ³ΠΎ

// Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ имССтся ΠΏΠΎΠ±ΠΎΡ‡Π½ΠΎΠ΅ дСйствиС, Ρ‚Π°ΠΊ Ρ‡Ρ‚ΠΎ трСбуСтся

// ΡƒΠ»ΡƒΡ‡ΡˆΠ΅Π½ΠΈΠ΅ этого ΠΌΠ΅Ρ‚ΠΎΠ΄Π°)

class B { // ...

public:

 explicit B(const B& rhs);

};


class D : public B { /* ... */ };

Π’Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΉ ΠΊΠΎΠ΄ всС Ρ€Π°Π²Π½ΠΎ Π² состоянии Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ срСзку, Ссли это Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ, Π½ΠΎ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π΄Π΅Π»Π°Ρ‚ΡŒ это явно:

void Transmogrify(B obj); // Π’Π΅ΠΏΠ΅Ρ€ΡŒ эта функция Π²ΠΎΠΎΠ±Ρ‰Π΅ Π½Π΅

                          // ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π²Ρ‹Π·Π²Π°Π½Π° (!)


void Transmogrify2(const B& obj) // Идиома для намСрСния Π²

{                                // любом случаС ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ

 Π’ b( obj );                     // ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ obj ΠΏΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ

 // ...                          // (с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ срСзкой)

}


B b;              // Π‘Π°Π·ΠΎΠ²Ρ‹Π΅ классы Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π±Ρ‹Ρ‚ΡŒ ΠΊΠΎΠ½ΠΊΡ€Π΅Ρ‚Π½Ρ‹ΠΌΠΈ

D d;              // (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 35), Π½ΠΎ допустим это

Transmogrify(b);  // Π”ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ ошибка (см. ΠΏΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅)

Transmogrify(d);  // Π”ΠΎΠ»ΠΆΠ½Π° Π±Ρ‹Ρ‚ΡŒ ошибка (см. ΠΏΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅)

Transmogrify2(d); // ВсС Π² порядкС

ΠŸΡ€ΠΈΠΌΠ΅Ρ‡Π°Π½ΠΈΠ΅: Π½Π° ΠΌΠΎΠΌΠ΅Π½Ρ‚ написания Π΄Π°Π½Π½ΠΎΠΉ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΠΈ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ компиляторы ΠΎΡˆΠΈΠ±ΠΎΡ‡Π½ΠΎ допускали ΠΎΠ΄ΠΈΠ½ ΠΈΠ»ΠΈ ΠΎΠ±Π° ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Ρ‹Ρ… Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Transmogrify. Π­Ρ‚Π° ΠΈΠ΄ΠΈΠΎΠΌΠ° Π²ΠΏΠΎΠ»Π½Π΅ стандартна, Π½ΠΎ (ΠΏΠΎΠΊΠ° Ρ‡Ρ‚ΠΎ) Π½Π΅ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ пСрСносима.

Π˜ΠΌΠ΅Π΅Ρ‚ΡΡ Π»ΡƒΡ‡ΡˆΠΈΠΉ способ прСдупрСТдСния срСзки, с Π±ΠΎΠ»Π΅Π΅ высокой ΡΡ‚Π΅ΠΏΠ΅Π½ΡŒΡŽ пСрСносимости. ΠŸΡƒΡΡ‚ΡŒ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, функция Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ Transmogrify Π² Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ Ρ…ΠΎΡ‡Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡ΠΈΡ‚ΡŒ ΠΏΠΎΠ»Π½ΡƒΡŽ Π³Π»ΡƒΠ±ΠΎΠΊΡƒΡŽ копию Π±Π΅Π· ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ ΠΎ Π΄Π΅ΠΉΡΡ‚Π²ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠΌ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½ΠΎΠΌ Ρ‚ΠΈΠΏΠ΅ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Π‘ΠΎΠ»Π΅Π΅ ΠΎΠ±Ρ‰Π΅Π΅ идиоматичСскоС Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ состоит Π² Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡΠ΄Π΅Π»Π°Ρ‚ΡŒ ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΉ конструктор Π±Π°Π·ΠΎΠ²ΠΎΠ³ΠΎ класса Π·Π°Ρ‰ΠΈΡ‰Π΅Π½Π½Ρ‹ΠΌ (Ρ‡Ρ‚ΠΎΠ±Ρ‹ функция Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ Transmogrify Π½Π΅ ΠΌΠΎΠ³Π»Π° случайно Π΅Π³ΠΎ Π²Ρ‹Π·Π²Π°Ρ‚ΡŒ), Π° вмСсто Π½Π΅Π³ΠΎ Π²ΠΎΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠ΅ΠΉ Clone:

// Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Clone (ΡƒΠΆΠ΅ Π»ΡƒΡ‡ΡˆΠ΅, Π½ΠΎ всС Π΅Ρ‰Π΅ трСбуСтся

// ΡƒΡΠΎΠ²Π΅Ρ€ΡˆΠ΅Π½ΡΡ‚Π²ΠΎΠ²Π°Π½ΠΈΠ΅)

class B { // ...

public:

 virtual B* Clone() const = 0;

protected:

 B(const B&);

};


class D : public B { // ...

public:

 virtual D* Clone() const { return new D(*this); }

protected:

 D( const D& rhs ): B(rhs) {/*...*/ }

};

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ° срСзки Π±ΡƒΠ΄Π΅Ρ‚ (пСрСносимо) Π³Π΅Π½Π΅Ρ€ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ ΠΎΡˆΠΈΠ±ΠΊΡƒ Π²Ρ€Π΅ΠΌΠ΅Π½ΠΈ компиляции, Π° объявлСниС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Clone ΠΊΠ°ΠΊ чисто Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠΉ заставляСт нСпосрСдствСнный ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹ΠΉ класс ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Ρ‚ΡŒ Π΅Π΅. К соТалСнию, с Π΄Π°Π½Π½Ρ‹ΠΌ Ρ€Π΅ΡˆΠ΅Π½ΠΈΠ΅ΠΌ всС Π΅Ρ‰Π΅ связаны Π΄Π²Π΅ ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΡ‹, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ компилятор Π½Π΅ Π² состоянии ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ΡŒ: Π² классС, ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½ΠΎΠΌ ΠΎΡ‚ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½ΠΎΠ³ΠΎ, функция Clone ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ Π½Π΅ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Ρ‚ΠΎΠΉ, Π° ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Ρ‚ΠΈΠ΅ Clone ΠΌΠΎΠΆΠ΅Ρ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π΅Π΅ Π½Π΅ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎ, Ρ‚Π°ΠΊ Ρ‡Ρ‚ΠΎ копия Π±ΡƒΠ΄Π΅Ρ‚ Π½Π΅ Ρ‚ΠΎΠ³ΠΎ ΠΆΠ΅ Ρ‚ΠΈΠΏΠ°, Ρ‡Ρ‚ΠΎ ΠΈ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π». Ѐункция Clone Π΄ΠΎΠ»ΠΆΠ½Π° ΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚ΡŒ ΡˆΠ°Π±Π»ΠΎΠ½Ρƒ проСктирования Nonvirtual Interface (NVI; см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 39), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ раздСляСт ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚ΡƒΡŽ ΠΈ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΏΡ€ΠΈΡ€ΠΎΠ΄Ρ‹ Clone ΠΈ позволяСт Π²Π°ΠΌ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ряд Π²Π°ΠΆΠ½Ρ‹Ρ… ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΎΠΊ:

class Π’ { // ...

publiс:

 B* Clone() const { // ΠΠ΅Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Π°Ρ функция

  B* Ρ€ = DoClone();

  assert(typeid(*p) == typeid(*this) &&

   "DoClone incorrectly overridden");

  return p; // ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Ρ‚ΠΈΠΏΠ°, Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ DoClone

 }

protected:

 B(const B&);

private:

 virtual B* DoClone() const = 0;

};

Ѐункция Clone Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ являСтся Π½Π΅Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΌ интСрфСйсом, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌΡ‹ΠΌ Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰ΠΈΠΌ ΠΊΠΎΠ΄ΠΎΠΌ. ΠŸΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½Ρ‹Π΅ классы Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ DoClone. Π”ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠΈΡ‚ всС ΠΊΠΎΠΏΠΈΠΈ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ ΠΈΠΌΠ΅ΡŽΡ‚ Ρ‚ΠΈΠΏ, ΠΎΡ‚Π»ΠΈΡ‡Π½Ρ‹ΠΉ ΠΎΡ‚ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»Π°, Ρ‚Π΅ΠΌ самым оповСщая, Ρ‡Ρ‚ΠΎ Π² Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌ ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ΄Π½ΠΎΠΌ классС Π½Π΅ ΠΏΠ΅Ρ€Π΅ΠΊΡ€Ρ‹Ρ‚Π° функция DoClone; Π² ΠΊΠΎΠ½Ρ†Π΅ ΠΊΠΎΠ½Ρ†ΠΎΠ², Π·Π°Π΄Π°Ρ‡Π° assert состоит ΠΈΠΌΠ΅Π½Π½ΠΎ Π² ΠΎΠ±Π½Π°Ρ€ΡƒΠΆΠ΅Π½ΠΈΠΈ ΠΈ сообщСнии ΠΎ Ρ‚Π°ΠΊΠΈΡ… ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½Ρ‹Ρ… ΠΎΡˆΠΈΠ±ΠΊΠ°Ρ… (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΠΈ 68 ΠΈ 70).

Π˜ΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ

НСкоторыС ΠΏΡ€ΠΎΠ΅ΠΊΡ‚Π½Ρ‹Π΅ Ρ€Π΅ΡˆΠ΅Π½ΠΈΡ ΠΌΠΎΠ³ΡƒΡ‚ Ρ‚Ρ€Π΅Π±ΠΎΠ²Π°Ρ‚ΡŒ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‰ΠΈΠ΅ конструкторы Π±Π°Π·ΠΎΠ²Ρ‹Ρ… классов ΠΎΡΡ‚Π°Π²Π°Π»ΠΈΡΡŒ ΠΎΡ‚ΠΊΡ€Ρ‹Ρ‚Ρ‹ΠΌΠΈ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΊΠΎΠ³Π΄Π° Ρ‡Π°ΡΡ‚ΡŒ вашСй ΠΈΠ΅Ρ€Π°Ρ€Ρ…ΠΈΠΈ прСдставляСт собой Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΡƒ стороннСго производитСля). Π’ Ρ‚Π°ΠΊΠΎΠΌ случаС слСдуСт ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Π΅ΡΡ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Ρƒ посрСдством (ΠΈΠ½Ρ‚Π΅Π»Π»Π΅ΠΊΡ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠ³ΠΎ) указатСля ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ ΠΏΠΎ ссылкС; ΠΊΠ°ΠΊ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π² Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΠΈ 25, ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π° посрСдством указатСля сущСствСнно ΠΌΠ΅Π½Π΅Π΅ ΠΏΠΎΠ΄Π²Π΅Ρ€ΠΆΠ΅Π½Π° срСзкС ΠΈ Π½Π΅ΠΆΠ΅Π»Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΠΌΡƒ созданию Π²Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ².

Бсылки

[Dewhurst03] Β§30, Β§76, Β§94 β€’ [Meyers96] Β§13 β€’ [Meyers97] Β§22 β€’ [Stroustrup94] Β§11.4.4 β€’ [Stroustrup00] Β§12.2.3

55. ΠŸΡ€Π΅Π΄ΠΏΠΎΡ‡ΠΈΡ‚Π°ΠΉΡ‚Π΅ каноничСский Π²ΠΈΠ΄ присваивания

РСзюмС

ΠŸΡ€ΠΈ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° operator= ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ каноничСский Π²ΠΈΠ΄ β€” Π½Π΅Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΉ с ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠΉ сигнатурой.

ΠžΠ±ΡΡƒΠΆΠ΄Π΅Π½ΠΈΠ΅

ΠŸΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ ΠΎΠ±ΡŠΡΠ²Π»ΡΡ‚ΡŒ ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ присваиваниС для Ρ‚ΠΈΠΏΠ° T с ΠΎΠ΄Π½ΠΎΠΉ ΠΈΠ· ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… сигнатур (см. [Stroustrup00] ΠΈ [Alexandrescu03a]):

T& operator=(const T&); // классичСский Π²ΠΈΠ΄

T& operator=(T);        // ΠΏΠΎΡ‚Π΅Π½Ρ†ΠΈΠ°Π»ΡŒΠ½ΠΎ ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ

                        // Π²ΠΈΠ΄ (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 27)

Π’Ρ‚ΠΎΡ€ΠΎΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΠΈΠΌΠ΅Π΅Ρ‚ смысл ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ, Ссли Π²Π°ΠΌ Π² любом случаС трСбуСтся копия Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° Π² Ρ‚Π΅Π»Π΅ вашСго ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π°, ΠΊΠ°ΠΊ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, ΠΏΡ€ΠΈ использовании ΠΈΠ΄ΠΈΠΎΠΌΡ‹, основанной Π½Π° использовании Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΎΠ±ΠΌΠ΅Π½Π° (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 56).

Π˜Π·Π±Π΅Π³Π°ΠΉΡ‚Π΅ Π΄Π΅Π»Π°Ρ‚ΡŒ любой ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присваивания Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½Ρ‹ΠΌ (см. [Meyers96] Β§33 ΠΈ [Sutter04] Β§19). Если Π²Ρ‹ ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚Π΅, Ρ‡Ρ‚ΠΎ Π²Π°ΠΌ трСбуСтся Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΠΎΠ΅ ΠΏΠΎΠ²Π΅Π΄Π΅Π½ΠΈΠ΅ присваивания, ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ΡΡŒ сначала ΠΊ ΡƒΠΊΠ°Π·Π°Π½Π½ΠΎΠΉ Π»ΠΈΡ‚Π΅Ρ€Π°Ρ‚ΡƒΡ€Π΅. Если ΠΈ послС этого Π²Ρ‹ стоитС Π½Π° своСм, Ρ‚ΠΎ Π»ΡƒΡ‡ΡˆΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π²ΠΈΡ€Ρ‚ΡƒΠ°Π»ΡŒΠ½ΡƒΡŽ ΠΈΠΌΠ΅Π½ΠΎΠ²Π°Π½Π½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ, Π° Π½Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, virtual void Assign(const T&);).

He Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΠΉΡ‚Π΅ const T&. Π₯отя этот Ρ‚ΠΈΠΏ Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅ΠΌΠΎΠ³ΠΎ значСния ΠΈΠΌΠ΅Π΅Ρ‚ Ρ‚ΠΎ прСимущСство, Ρ‡Ρ‚ΠΎ Π·Π°Ρ‰ΠΈΡ‰Π°Π΅Ρ‚ ΠΎΡ‚ странных присваиваний Π½Π°ΠΏΠΎΠ΄ΠΎΠ±ΠΈΠ΅ (a=b)=c, Π³Π»Π°Π²Π½Ρ‹ΠΌ Π΅Π³ΠΎ нСдостатком являСтся Ρ‚ΠΎ, Ρ‡Ρ‚ΠΎ Π²Ρ‹ Π½Π΅ смоТСтС ΠΏΠΎΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Ρ‚ΠΈΠΏΠ° T Π² ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ стандартной Π±ΠΈΠ±Π»ΠΈΠΎΡ‚Π΅ΠΊΠΈ; эти ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€Ρ‹ Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присваивания Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π» Ρ‚ΠΈΠΏ T&.

ВсСгда Π΄Π΅Π»Π°ΠΉΡ‚Π΅ ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ присваиваниС бСзопасным Π² смыслС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ, ΠΏΡ€ΠΈΡ‡Π΅ΠΌ ΠΏΡ€Π΅Π΄ΠΏΠΎΡ‡Ρ‚ΠΈΡ‚Π΅Π»ΡŒΠ½Π° строгая гарантия (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 71).

Π£Π±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ ваш ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присваивания бСзопасСн Π² смыслС присваивания самому сСбС. Π˜Π·Π±Π΅Π³Π°ΠΉΡ‚Π΅ написания ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ присваивания, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ для ΠΊΠΎΡ€Ρ€Π΅ΠΊΡ‚Π½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹ полагаСтся Π½Π° ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΡƒ присваивания самому сСбС; Π·Π°Ρ‡Π°ΡΡ‚ΡƒΡŽ это Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚ ΠΎ нСдостаточной бСзопасности Π² смыслС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ. Если Π²Ρ‹ ΠΏΠΈΡˆΠ΅Ρ‚Π΅ ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ присваиваниС с использованиСм ΠΈΠ΄ΠΈΠΎΠΌΡ‹ ΠΎΠ±ΠΌΠ΅Π½Π° (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 56), Ρ‚ΠΎ Π²Ρ‹ автоматичСски обСспСчиваСтС ΠΊΠ°ΠΊ ΡΡ‚Ρ€ΠΎΠ³ΡƒΡŽ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ Π² смыслС ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠΉ, Ρ‚Π°ΠΊ ΠΈ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡ‚ΡŒ Π² смыслС присваивания самому сСбС. Если присваиваниС самому сСбС часто встрСчаСтся Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ ΠΈΠ·-Π·Π° использования ссылочных синонимов ΠΈΠ»ΠΈ ΠΏΠΎ ΠΊΠ°ΠΊΠΈΠΌ-Ρ‚ΠΎ ΠΈΠ½Ρ‹ΠΌ ΠΏΡ€ΠΈΡ‡ΠΈΠ½Π°ΠΌ, ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° присваивания самому сСбС ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ Π² качСствС срСдства ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·Π°Ρ†ΠΈΠΈ Π²ΠΎ ΠΈΠ·Π±Π΅ΠΆΠ°Π½ΠΈΠ΅ лишнСй Ρ€Π°Π±ΠΎΡ‚Ρ‹.

Π―Π²Π½ΠΎ Π²Ρ‹Π·Ρ‹Π²Π°ΠΉΡ‚Π΅ всС ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ присваивания Π±Π°Π·ΠΎΠ²Ρ‹Ρ… классов ΠΈ всСх Π΄Π°Π½Π½Ρ‹Ρ…-Ρ‡Π»Π΅Π½ΠΎΠ² ([Meyers97] Β§16); ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅, Ρ‡Ρ‚ΠΎ ΠΈΠ΄ΠΈΠΎΠΌΠ° ΠΎΠ±ΠΌΠ΅Π½Π° автоматичСски заботится ΠΎΠ±ΠΎ всСх этих Π²Π΅Ρ‰Π°Ρ…. Π’ΠΎΠ·Π²Ρ€Π°Ρ‰Π°ΠΉΡ‚Π΅ ΠΈΠ· ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° присваивания Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ *this ([Meyers97] Β§15).

Бсылки

[Alexandrescu03a] β€’ [Cargill92] pp. 41-42, 95 β€’ [Cline99] Β§24.01-12 β€’ [Koenig97] Β§4 β€’ [Meyers96] Β§33 β€’ [Meyers97] Β§17 β€’ [Murray93] Β§2.2.1 β€’ [Stroustrup00] Β§10.4.4.1, Β§10.4.6.3 β€’ [Sutter00] Β§13, Β§38, Β§41 β€’ [Sutter04] Β§19

56. ΠžΠ±Π΅ΡΠΏΠ΅Ρ‡ΡŒΡ‚Π΅ Π±Π΅ΡΡΠ±ΠΎΠΉΠ½ΡƒΡŽ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ ΠΎΠ±ΠΌΠ΅Π½Π°

РСзюмС

ΠžΠ±Ρ‹Ρ‡Π½ΠΎ ΠΈΠΌΠ΅Π΅Ρ‚ смысл ΠΏΡ€Π΅Π΄ΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ для класса Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ swap Π² цСлях эффСктивного ΠΈ бСссбойного ΠΎΠ±ΠΌΠ΅Π½Π° Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½Π΅Π³ΠΎ содСрТимого ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° с Π²Π½ΡƒΡ‚Ρ€Π΅Π½Π½ΠΈΠΌ содСрТимым Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°. Вакая функция ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΡ€ΠΈΠ³ΠΎΠ΄ΠΈΡ‚ΡŒΡΡ для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ряда ΠΈΠ΄ΠΈΠΎΠΌ, ΠΎΡ‚ простого пСрСмСщСния ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Π΄ΠΎ Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ присваивания, Π»Π΅Π³ΠΊΠΎ ΠΎΠ±Π΅ΡΠΏΠ΅Ρ‡ΠΈΠ²Π°ΡŽΡ‰Π΅Π³ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ принятия Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ΠΎΠ² Ρ€Π°Π±ΠΎΡ‚Ρ‹ со строгими гарантиями бСзопасности для Π²Ρ‹Π·Ρ‹Π²Π°ΡŽΡ‰Π΅Π³ΠΎ ΠΊΠΎΠ΄Π° (см. Ρ‚Π°ΠΊΠΆΠ΅ Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 51).

ΠžΠ±ΡΡƒΠΆΠ΄Π΅Π½ΠΈΠ΅

ΠžΠ±Ρ‹Ρ‡Π½ΠΎ функция swap выглядит ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ (здСсь U β€” Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΡΠΊΠΈΠΉ Ρ‚ΠΈΠΏ):

class T { // ...

public:

 void swap(T& rhs) {

  member1_.swap(rhs.member1_);

  std::swap(member2_, rhs.member2_);

 }

private:

 U member1_;

 int member2_;

};

Для ΠΏΡ€ΠΈΠΌΠΈΡ‚ΠΈΠ²Π½Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² ΠΈ стандартных ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ΠΎΠ² ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ std::swap. Π”Ρ€ΡƒΠ³ΠΈΠ΅ классы ΠΌΠΎΠ³ΡƒΡ‚ Ρ€Π΅Π°Π»ΠΈΠ·ΠΎΠ²Ρ‹Π²Π°Ρ‚ΡŒ ΠΎΠ±ΠΌΠ΅Π½ Π² Π²ΠΈΠ΄Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ-Ρ‡Π»Π΅Π½ΠΎΠ² с Ρ€Π°Π·Π»ΠΈΡ‡Π½Ρ‹ΠΌΠΈ ΠΈΠΌΠ΅Π½Π°ΠΌΠΈ.

Рассмотрим использованиС swap для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ присваивания посрСдством ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‰Π΅Π³ΠΎ конструктора. ΠŸΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π½Π°Ρ Π΄Π°Π»Π΅Π΅ рСализация ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° operator= обСспСчиваСт ΡΡ‚Ρ€ΠΎΠ³ΡƒΡŽ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡŽ (см. Ρ€Π΅ΠΊΠΎΠΌΠ΅Π½Π΄Π°Ρ†ΠΈΡŽ 71), хотя ΠΈ Ρ†Π΅Π½ΠΎΠΉ создания Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°, Ρ‡Ρ‚ΠΎ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΎΠΊΠ°Π·Π°Ρ‚ΡŒΡΡ Π½Π΅ΠΏΡ€ΠΈΠ΅ΠΌΠ»Π΅ΠΌΡ‹ΠΌ, Ссли имССтся Π±ΠΎΠ»Π΅Π΅ эффСктивный способ выполнСния бСзопасного присваивания ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² Ρ‚ΠΈΠΏΠ° T: