Kopírovat a vyměňovat

Izom copy-and-swap  je idiom programovacího jazyka C++ , který vám umožňuje navrhovat příkazy přiřazení tolerantní k výjimkám .

Tento idiom je založen na idiomu „ Získání zdroje se inicializuje “.

Tento idiom zahrnuje implementaci následujících funkcí členů třídy:

Příklad:

class Copyable { veřejnost : Copyable & operator = ( const Copyable & _v ) { kopírovatelný tmp ( _v ); toto -> swap ( tmp ); vrátit * toto ; } void swap ( Copyable & _v ) noexcept ; };

Tolerance výjimek znamená, Copyable& operator=(const Copyable &)že v příkazu přiřazení není žádný bod, kde by vyvolání výjimky způsobilo únik paměti.

Operátor přiřazení se nejprve pokusí získat zdroj „dočasné kopie přiřazovaného objektu“ ( tmp) a v případě úspěchu změní jeho obsah s obsahem aktuálního objektu ( this). Protože je metoda swapdeklarována jako nevyvolávající výjimky ( noexcept), jediným bodem, kde může dojít k výjimce, je kopírování objektu _v. Pokud se kopírování nezdaří, pak řízení nedosáhne metody swap, jinak destruktor objektu tmpuvolní prostředky, které dříve vlastnil aktuální objekt ( this) (viz idiom RAII ).

Výše uvedená implementace je odolná i vůči přiřazení objektu k sobě ( a=a), má však režii spojenou s tím, že i v tomto případě bude vytvořena dočasná kopie. Náklady můžete vyloučit dodatečnou kontrolou:

class Copyable { veřejnost : Copyable & operator = ( const Copyable & _v ) { if ( toto != & _v ) Kopírovatelné ( _v ). swap ( * toto ); vrátit * toto ; } void swap ( Copyable & _v ) noexcept ; };

Mnoho kontejnerů a algoritmů C++ Standard Library a STL předpokládá operátor přiřazení odolný vůči výjimkám, ale bez použití idiomu copy-and-swap je někdy docela obtížné implementovat takový operátor přiřazení pro třídy obsahující například ukazatele na instance jiné třídy.

Další operace

Máte-li členskou funkci swap, která nevyvolává výjimky, můžete použít podobnou techniku ​​k provedení jakékoli operace s objektem se silnou zárukou bezpečnou pro výjimky .

Chcete-li to provést, nejprve vytvořte kopii existujícího objektu, proveďte na kopii potřebné úpravy a poté změňte *thisdočasný objekt.

  • pokud konstruktor kopírování vyvolá výjimku, pak se původní objekt nezmění a je splněna záruka bezpečnosti silné výjimky;
  • pokud je vyvolána výjimka při změně dočasného objektu, pak bude na dočasný objekt zavolán destruktor a bude také splněna záruka, protože původní objekt nebyl změněn;
  • pokud byla změna na dočasný objekt úspěšná, spustí se swap a destruktor dočasného objektu, které nevyvolávají výjimky.

Viz také

  • Idiom nekopírovatelný