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

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«Π―Π·Ρ‹ΠΊ программирования C++. ΠŸΡΡ‚ΠΎΠ΅ ΠΈΠ·Π΄Π°Π½ΠΈΠ΅Β». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 183

Автор Π‘Ρ‚Π΅Π½Π»ΠΈ Π›ΠΈΠΏΠΏΠΌΠ°Π½

                          // присвоСниС пСрСмСщСния

Π’ ΠΏΠ΅Ρ€Π²ΠΎΠΌ случаС ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρƒ присвоСния пСрСдаСтся ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ v2. Π•Π³ΠΎ Ρ‚ΠΈΠΏΠΎΠΌ являСтся StrVec, Π° Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ v2 являСтся l-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ. ВСрсия присвоСния ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠΈ Π½Π΅ являСтся подходящСй (см. Ρ€Π°Π·Π΄Π΅Π» 6.6), ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ нСльзя нСявно ΡΠ²ΡΠ·Π°Ρ‚ΡŒ ссылку Π½Π° r-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ с l-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, Π² этом случаС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присвоСния ΠΊΠΎΠΏΠΈΠΈ.

Π’ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌ случаС присваиваСтся Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ getVec(), β€” это r-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Π’Π΅ΠΏΠ΅Ρ€ΡŒ подходящими ΡΠ²Π»ΡΡŽΡ‚ΡΡ ΠΎΠ±Π° ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° присвоСния β€” Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ getVec() ΠΌΠΎΠΆΠ½ΠΎ ΡΠ²ΡΠ·Π°Ρ‚ΡŒ с Π»ΡŽΠ±Ρ‹ΠΌ ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ΠΎΠΌ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π°. Π’Ρ‹Π·ΠΎΠ² ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° присвоСния ΠΊΠΎΠΏΠΈΠΈ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ прСобразования Π² константу, Π² Ρ‚ΠΎ врСмя ΠΊΠ°ΠΊ StrVec&& обСспСчиваСт Ρ‚ΠΎΡ‡Π½ΠΎΠ΅ соотвСтствиС. Π‘Π»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎ, Π²Ρ‚ΠΎΡ€ΠΎΠ΅ присвоСниС ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присваивания ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠΈ.

…но r-значСния ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‚ΡΡ, Ссли Π½Π΅Ρ‚ конструктора пСрСмСщСния

Π§Ρ‚ΠΎ Ссли класс ΠΈΠΌΠ΅Π΅Ρ‚ конструктор ΠΊΠΎΠΏΠΈΠΉ, Π½ΠΎ Π½Π΅ опрСдСляСт конструктор пСрСмСщСния? Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС компилятор Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΈΠ½Ρ‚Π΅Π·ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ конструктор пСрСмСщСния. Π­Ρ‚ΠΎ Π·Π½Π°Ρ‡ΠΈΡ‚, Ρ‡Ρ‚ΠΎ Ρƒ класса Π΅ΡΡ‚ΡŒ конструктор ΠΊΠΎΠΏΠΈΠΉ, Π½ΠΎ Π½Π΅Ρ‚ конструктора пСрСмСщСния. Если Ρƒ класса Π½Π΅Ρ‚ конструктора пСрСмСщСния, ΠΏΠΎΠ΄Π±ΠΎΡ€ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΡƒΠ΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ этого Ρ‚ΠΈΠΏΠ° Π±ΡƒΠ΄ΡƒΡ‚ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒΡΡ, Π΄Π°ΠΆΠ΅ ΠΏΡ€ΠΈ ΠΏΠΎΠΏΡ‹Ρ‚ΠΊΠ΅ пСрСмСщСния ΠΈΡ… Π²Ρ‹Π·ΠΎΠ²ΠΎΠΌ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ move():

class Foo {

public:

 Foo() = default;

 Foo(const Foo&); // конструктор ΠΊΠΎΠΏΠΈΠΉ

 // Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Ρ‡Π»Π΅Π½Ρ‹, Π½ΠΎ Foo Π½Π΅ опрСдСляСт конструктор пСрСмСщСния

};

Foo x;

Foo y(x);            // конструктор ΠΊΠΎΠΏΠΈΠΉ; x - это l-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅

Foo z(std::move(x)); // конструктор ΠΊΠΎΠΏΠΈΠΉ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ конструктора

                     // пСрСмСщСния Π½Π΅Ρ‚

Π’Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ move(x) ΠΏΡ€ΠΈ ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° z Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Foo&&, привязанный ΠΊ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρƒ x. ΠšΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ‚ΠΎΡ€ ΠΊΠΎΠΏΠΈΠΉ для класса Foo являСтся подходящим, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π²ΠΏΠΎΠ»Π½Π΅ допустимо ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Foo&& Π² const Foo&. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, инициализация ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° z ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ конструктор ΠΊΠΎΠΏΠΈΠΉ класса Foo.

Π‘Π»Π΅Π΄ΡƒΠ΅Ρ‚ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ использованиС конструктора ΠΊΠΎΠΏΠΈΠΉ вмСсто конструктора пСрСмСщСния ΠΏΠΎΡ‡Ρ‚ΠΈ бСзусловно бСзопасно (Ρ‚ΠΎ ΠΆΠ΅ справСдливо ΠΈ для ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° присвоСния). ΠžΠ±Ρ‹Ρ‡Π½ΠΎ конструктор ΠΊΠΎΠΏΠΈΠΉ ΠΎΡ‚Π²Π΅Ρ‡Π°Π΅Ρ‚ трСбованиям ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π³ΠΎ конструктора пСрСмСщСния: ΠΎΠ½ ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ Π·Π°Π΄Π°Π½Π½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ ΠΈ оставляСт ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ Π² допустимом состоянии. ΠšΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ‚ΠΎΡ€ ΠΊΠΎΠΏΠΈΠΉ, Π½Π°ΠΏΡ€ΠΎΡ‚ΠΈΠ², Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΠ·ΠΌΠ΅Π½ΡΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°.

Если Ρƒ класса Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΈΠ³ΠΎΠ΄Π½Ρ‹ΠΉ конструктор ΠΊΠΎΠΏΠΈΠΉ ΠΈ Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ конструктора пСрСмСщСния, Ρ‚ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ Π±ΡƒΠ΄ΡƒΡ‚ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½Ρ‹ конструктором ΠΊΠΎΠΏΠΈΠΉ. Π’ΠΎ ΠΆΠ΅ справСдливо для ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° присвоСния ΠΊΠΎΠΏΠΈΠΈ ΠΈ присвоСния ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠΈ.

ΠžΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ присвоСния ΠΊΠΎΠΏΠΈΠΈ ΠΈ ΠΎΠ±ΠΌΠ΅Π½Π° ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠ΅

ВСрсия класса HasPtr, ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΠ²ΡˆΠ°Ρ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присвоСния ΠΊΠΎΠΏΠΈΠΈ ΠΈ ΠΎΠ±ΠΌΠ΅Π½Π° (copy-and-swap assignment operator) (см. Ρ€Π°Π·Π΄Π΅Π» 13.3), β€” Ρ…ΠΎΡ€ΠΎΡˆΠ°Ρ ΠΈΠ»Π»ΡŽΡΡ‚Ρ€Π°Ρ†ΠΈΡ взаимодСйствия ΠΌΠ΅Ρ…Π°Π½ΠΈΠ·ΠΌΠ° ΠΏΠΎΠ΄Π±ΠΎΡ€Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ пСрСмСщСния. Если Π² этот класс Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ конструктор пСрСмСщСния, Ρ‚ΠΎ фактичСски Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ Ρ‚Π°ΠΊΠΆΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присваивания ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠΈ:

class HasPtr {

public:

 // Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ конструктор пСрСмСщСния

 HasPtr(HasPtr &&p) noexcept : ps(p.ps), i(p.i) {p.ps = 0;}

 // ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присвоСния - ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ пСрСмСщСния, ΠΈ присвоСния ΠΊΠΎΠΏΠΈΠΈ

 HasPtr& operator=(HasPtr rhs)

  { swap(*this, rhs); return *this; }

 // Π΄Ρ€ΡƒΠ³ΠΈΠ΅ Ρ‡Π»Π΅Π½Ρ‹ ΠΊΠ°ΠΊ Π² p. 13.2.1

};

Π’ этой вСрсии класса Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ конструктор пСрСмСщСния, ΠΏΠΎΠ»ΡƒΡ‡Π°ΡŽΡ‰ΠΈΠΉ значСния ΠΈΠ· своСго Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π°. Π’Π΅Π»ΠΎ конструктора обнуляСт ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ-Ρ‡Π»Π΅Π½ Π΄Π°Π½Π½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° класса HasPtr, Ρ‡Ρ‚ΠΎΠ±Ρ‹ Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ бСзопасноС ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½ΠΎΠ³ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° пСрСмСщСния. Π­Ρ‚Π° функция Π½Π΅ Π΄Π΅Π»Π°Π΅Ρ‚ Π½ΠΈΡ‡Π΅Π³ΠΎ, ΠΎΠ½Π° Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅, поэтому ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΠΌ Π΅Π΅ ΠΊΠ°ΠΊ noexcept (см. Ρ€Π°Π·Π΄Π΅Π» 13.6.2).

Π’Π΅ΠΏΠ΅Ρ€ΡŒ рассмотрим ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присвоСния. Π£ Π½Π΅Π³ΠΎ Π΅ΡΡ‚ΡŒ Π½Π΅ ссылочный ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€, Π° Π·Π½Π°Ρ‡ΠΈΡ‚, этот ΠΏΠ°Ρ€Π°ΠΌΠ΅Ρ‚Ρ€ инициализируСтся ΠΊΠΎΠΏΠΈΠ΅ΠΉ (см. Ρ€Π°Π·Π΄Π΅Π» 13.1.1). Π’ зависимости ΠΎΡ‚ Ρ‚ΠΈΠΏΠ° Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚Π° инициализация ΠΊΠΎΠΏΠΈΠ΅ΠΉ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ Π»ΠΈΠ±ΠΎ конструктор ΠΊΠΎΠΏΠΈΠΉ, Π»ΠΈΠ±ΠΎ конструктор пСрСмСщСния; l-значСния ΠΊΠΎΠΏΠΈΡ€ΡƒΡŽΡ‚ΡΡ, Π° r-значСния ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°ΡŽΡ‚ΡΡ. Π’ Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚Π΅ этот ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ ΠΎΠ΄Π½ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎΠ³ΠΎ присвоСния дСйствуСт ΠΈ ΠΊΠ°ΠΊ присвоСниС ΠΊΠΎΠΏΠΈΠΈ, ΠΈ ΠΊΠ°ΠΊ присваиваниС ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠΈ.

ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»ΠΎΠΆΠΈΠΌ, Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, Ρ‡Ρ‚ΠΎ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Ρ‹ hp ΠΈ hp2 ΡΠ²Π»ΡΡŽΡ‚ΡΡ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π°ΠΌΠΈ класса HasPtr:

hp = hp2; // hp2 - l-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅; для копирования hp2 ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ

          // конструктор ΠΊΠΎΠΏΠΈΠΉ

hp = std::move(hp2); // hp2 ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π°Π΅Ρ‚ конструктор пСрСмСщСния

Π’ ΠΏΠ΅Ρ€Π²ΠΎΠΌ случаС присвоСния ΠΏΡ€Π°Π²Ρ‹ΠΉ ΠΎΠΏΠ΅Ρ€Π°Π½Π΄ β€” l-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, поэтому конструктор пСрСмСщСния Π½Π΅ ΠΏΠΎΠ΄Ρ…ΠΎΠ΄ΠΈΡ‚. Для ΠΈΠ½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ rhs Π±ΡƒΠ΄Π΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒΡΡ конструктор ΠΊΠΎΠΏΠΈΠΉ. Он Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π΅Π·Π΅Ρ€Π²ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Π½ΠΎΠ²ΡƒΡŽ строку ΠΈ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ‚Ρƒ строку, Π½Π° ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π΅Ρ‚ hp2.

Π’ΠΎ Π²Ρ‚ΠΎΡ€ΠΎΠΌ случаС присвоСния вызываСтся функция std::move() для связывания ссылки Π½Π° r-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ с ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠΌ hp2. Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС подходят ΠΈ конструктор ΠΊΠΎΠΏΠΈΠΉ, ΠΈ конструктор пСрСмСщСния. Но ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π°Ρ€Π³ΡƒΠΌΠ΅Π½Ρ‚ β€” это ссылка Π½Π° r-Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Ρ‚ΠΎΡ‡Π½ΠΎΠ΅ соотвСтствиС обСспСчит конструктор пСрСмСщСния. ΠšΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ‚ΠΎΡ€ пСрСмСщСния ΠΊΠΎΠΏΠΈΡ€ΡƒΠ΅Ρ‚ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ ΠΈΠ· ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° hp2 ΠΈ Π½Π΅ Ρ€Π΅Π·Π΅Ρ€Π²ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΏΠ°ΠΌΡΡ‚ΡŒ.

НСзависимо ΠΎΡ‚ Ρ‚ΠΎΠ³ΠΎ, использовался Π»ΠΈ конструктор ΠΊΠΎΠΏΠΈΠΈ ΠΈΠ»ΠΈ пСрСмСщСния, Ρ‚Π΅Π»ΠΎ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Π° присвоСния ΠΎΠ±ΠΌΠ΅Π½ΠΈΠ²Π°Π΅Ρ‚ содСрТимоС Π΄Π²ΡƒΡ… своих ΠΎΠΏΠ΅Ρ€Π°Π½Π΄ΠΎΠ². ОбмСн ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ² класса HasPtr ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ ΠΎΠ±ΠΌΠ΅Π½Ρƒ указатСлями-Ρ‡Π»Π΅Π½Π°ΠΌΠΈ ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹ΠΌΠΈ-Ρ‡Π»Π΅Π½Π°ΠΌΠΈ (Ρ‚ΠΈΠΏΠ° int) этих Π΄Π²ΡƒΡ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ². ПослС Π²Ρ‹Π·ΠΎΠ²Π° Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ swap() ΠΏΡ€Π°Π²Ρ‹ΠΉ ΠΎΠΏΠ΅Ρ€Π°Π½Π΄ Π±ΡƒΠ΄Π΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° строку, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Ρ€Π°Π½Π΅Π΅ ΠΏΡ€ΠΈΠ½Π°Π΄Π»Π΅ΠΆΠ°Π» Π»Π΅Π²ΠΎΠΌΡƒ. ΠŸΡ€ΠΈ Π²Ρ‹Ρ…ΠΎΠ΄Π΅ rhs ΠΈΠ· области видимости эта строка Π±ΡƒΠ΄Π΅Ρ‚ ΡƒΠ΄Π°Π»Π΅Π½Π°.

Π‘ΠΎΠ²Π΅Ρ‚. ОбновлСнноС ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ Ρ‚Ρ€Π΅Ρ…

ВсС ΠΏΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ-Ρ‡Π»Π΅Π½ΠΎΠ² управлСния ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΌΠΎΠΆΠ½ΠΎ ΡΡ‡ΠΈΡ‚Π°Ρ‚ΡŒ Π΅Π΄ΠΈΠ½Ρ‹ΠΌ Π±Π»ΠΎΠΊΠΎΠΌ: Ссли класс опрСдСляСт Π»ΡŽΠ±ΡƒΡŽ ΠΈΠ· этих Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ, ΠΎΠ½ Π΄ΠΎΠ»ΠΆΠ΅Π½ ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ ΠΈΡ… всС. Как ΡƒΠΆΠ΅ ΡƒΠΏΠΎΠΌΠΈΠ½Π°Π»ΠΎΡΡŒ, для ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎΠΉ Ρ€Π°Π±ΠΎΡ‚Ρ‹ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ классы Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ конструктор ΠΊΠΎΠΏΠΈΠΉ, ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присвоСния ΠΊΠΎΠΏΠΈΠΈ ΠΈ дСструктор (см. Ρ€Π°Π·Π΄Π΅Π» 13.6). Как ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ, Ρƒ Ρ‚Π°ΠΊΠΈΡ… классов Π΅ΡΡ‚ΡŒ рСсурс, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ-Ρ‡Π»Π΅Π½Ρ‹ копирования. ΠžΠ±Ρ‹Ρ‡Π½ΠΎ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅ рСсурса Π²Π»Π΅Ρ‡Π΅Ρ‚ Π·Π° собой Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ Π·Π°Ρ‚Ρ€Π°Ρ‚Ρ‹. ΠšΠ»Π°ΡΡΡ‹, ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰ΠΈΠ΅ конструктор пСрСмСщСния ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присваивания ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠΈ, ΠΌΠΎΠ³ΡƒΡ‚ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ этих Π·Π°Ρ‚Ρ€Π°Ρ‚ Π² Ρ‚Π΅Ρ… ΠΎΠ±ΡΡ‚ΠΎΡΡ‚Π΅Π»ΡŒΡΡ‚Π²Π°Ρ…, Π³Π΄Π΅ копия Π½Π΅ ΠΎΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Π°.

Π€ΡƒΠ½ΠΊΡ†ΠΈΠΈ пСрСмСщСния для класса Message

ΠšΠ»Π°ΡΡΡ‹, ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‰ΠΈΠ΅ собствСнный конструктор ΠΊΠΎΠΏΠΈΠΉ ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присвоСния ΠΊΠΎΠΏΠΈΠΈ, ΠΎΠ±Ρ‹Ρ‡Π½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡŽΡ‚ ΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ пСрСмСщСния. НапримСр, наши классы Message ΠΈ Folder (см. Ρ€Π°Π·Π΄Π΅Π» 13.4), Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ пСрСмСщСния. ΠŸΡ€ΠΈ ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠΈ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ пСрСмСщСния класс Message ΠΌΠΎΠΆΠ΅Ρ‚ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ пСрСмСщСния классов string ΠΈ set, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΠΈΠ·Π±Π΅ΠΆΠ°Ρ‚ΡŒ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Ρ… Π·Π°Ρ‚Ρ€Π°Ρ‚ ΠΏΡ€ΠΈ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠΈ Ρ‡Π»Π΅Π½ΠΎΠ² contents ΠΈ folders.

Но Π² Π΄ΠΎΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΊ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΡŽ Ρ‡Π»Π΅Π½Π° folders слСдуСт Ρ‚Π°ΠΊΠΆΠ΅ ΠΎΠ±Π½ΠΎΠ²ΠΈΡ‚ΡŒ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ класса Folder, ΡƒΠΊΠ°Π·Ρ‹Π²Π°Π²ΡˆΠΈΠΉ Π½Π° ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π» ΠΎΠ±ΡŠΠ΅ΠΊΡ‚Π° класса Message. Π‘Π»Π΅Π΄ΡƒΠ΅Ρ‚ Ρ‚Π°ΠΊΠΆΠ΅ ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ Π½Π° ΠΏΡ€Π΅ΠΆΠ½ΠΈΠΉ ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ класса Message ΠΈ Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ Π½Π° Π½ΠΎΠ²Ρ‹ΠΉ.

И конструктор пСрСмСщСния, ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присваивания ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠΈ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ ΠΎΠ±Π½ΠΎΠ²Π»ΡΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ Folder, поэтому Π½Π°Ρ‡Π½Π΅ΠΌ с опрСдСлСния Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ для выполнСния этих дСйствий:

// ΠΏΠ΅Ρ€Π΅ΠΌΠ΅ΡΡ‚ΠΈΡ‚ΡŒ ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΠΈ Folder ΠΈΠ· m Π² Π΄Π°Π½Π½ΠΎΠ΅ Message

void Message::move_Folders(Message *m) {

 folders = std::move(m->folders); // ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ присвоСниС пСрСмСщСния

                                  // класса set

 for (auto f : folders) { // для ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ Folder

  f->remMsg(m);    // ΡƒΠ΄Π°Π»ΠΈΡ‚ΡŒ старый Message ΠΈΠ· Folder

  f->addMsg(this); // Π΄ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ этот Message Π² этот Folder

 }

 m->folders.clear(); // Π³Π°Ρ€Π°Π½Ρ‚ΠΈΡ€ΠΎΠ²Π°Ρ‚ΡŒ бСзопасноС ΡƒΠ΄Π°Π»Π΅Π½ΠΈΠ΅ m

}

Ѐункция Π½Π°Ρ‡ΠΈΠ½Π°Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Ρƒ с пСрСмСщСния Π½Π°Π±ΠΎΡ€Π° folders. ΠŸΡ€ΠΈ Π²Ρ‹Π·ΠΎΠ²Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ move() ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присвоСния ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠΈ класса set, Π° Π½Π΅ Π΅Π³ΠΎ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ присвоСния ΠΊΠΎΠΏΠΈΠΈ. Если ΠΏΡ€ΠΎΠΏΡƒΡΡ‚ΠΈΡ‚ΡŒ Π²Ρ‹Π·ΠΎΠ² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ move(), ΠΊΠΎΠ΄ всС Ρ€Π°Π²Π½ΠΎ Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π±ΠΎΡ‚Π°Ρ‚ΡŒ, Π½ΠΎ осущСствляя Π½Π΅Π½ΡƒΠΆΠ½ΠΎΠ΅ ΠΊΠΎΠΏΠΈΡ€ΠΎΠ²Π°Π½ΠΈΠ΅. Π—Π°Ρ‚Π΅ΠΌ функция ΠΏΠ΅Ρ€Π΅Π±ΠΈΡ€Π°Π΅Ρ‚ ΠΏΠ°ΠΏΠΊΠΈ, удаляя ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π» сообщСния ΠΈ добавляя ΡƒΠΊΠ°Π·Π°Ρ‚Π΅Π»ΡŒ Π½Π° Π½ΠΎΠ²ΠΎΠ΅ сообщСниС.

Π‘Π»Π΅Π΄ΡƒΠ΅Ρ‚ Π·Π°ΠΌΠ΅Ρ‚ΠΈΡ‚ΡŒ, Ρ‡Ρ‚ΠΎ вставка элСмСнта Π² Π½Π°Π±ΠΎΡ€ ΠΌΠΎΠΆΠ΅Ρ‚ привСсти ΠΊ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‡Π΅ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠ΅ элСмСнта Π½Π° ΠΊΠΎΠ½Ρ‚Π΅ΠΉΠ½Π΅Ρ€ Ρ‚Ρ€Π΅Π±ΡƒΠ΅Ρ‚ рСзСрвирования памяти, Π²ΠΏΠΎΠ»Π½Π΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΏΠ΅Ρ€Π΅Π΄Π°Π½ΠΎ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΠ΅ bad_alloc (см. Ρ€Π°Π·Π΄Π΅Π» 12.1.2). Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Π² ΠΎΡ‚Π»ΠΈΡ‡ΠΈΠ΅ ΠΎΡ‚ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΉ пСрСмСщСния классов HasPtr ΠΈ StrVec, конструктор пСрСмСщСния ΠΈ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€Ρ‹ присваивания ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Ρ‰Π΅Π½ΠΈΠΈ класса Message ΠΌΠΎΠ³Π»ΠΈ Π±Ρ‹ ΠΏΠ΅Ρ€Π΅Π΄Π°Ρ‚ΡŒ ΠΈΡΠΊΠ»ΡŽΡ‡Π΅Π½ΠΈΡ, поэтому Π½Π΅ Π±ΡƒΠ΄Π΅ΠΌ ΠΎΡ‚ΠΌΠ΅Ρ‡Π°Ρ‚ΡŒ ΠΈΡ… ΠΊΠ°ΠΊ noexcept (см. Ρ€Π°Π·Π΄Π΅Π» 13.6.2).