Share via


Konstruktory kopírování a operátory přiřazení kopírování (C++)

Poznámka:

Počínaje jazykem C++11 jsou podporovány dva druhy přiřazení: zkopírování přiřazení a přesunutí přiřazení. V tomto článku "přiřazení" se rozumí přiřazení kopírování, pokud není výslovně uvedeno jinak. Informace o přiřazení přesunutí naleznete v tématu Konstruktory přesunutí a operátory přiřazení přesunutí (C++).

Operace přiřazení a operace inicializace způsobí, že jsou objekty zkopírovány.

  • Přiřazení: Pokud je hodnota jednoho objektu přiřazena jinému objektu, první objekt se zkopíruje do druhého objektu. Tento kód tedy zkopíruje hodnotu b do a:

    Point a, b;
    ...
    a = b;
    
  • Inicializace: Inicializace nastane, když deklarujete nový objekt, když předáte argumenty funkce podle hodnoty nebo když vrátíte hodnotu z funkce.

Pro objekty typu třídy lze definovat sémantiku „kopie“. Podívejte se například na tento kód:

TextFile a, b;
a.Open( "FILE1.DAT" );
b.Open( "FILE2.DAT" );
b = a;

Předchozí kód by mohl znamenat "kopírovat obsah SOUBORU1. DAT do FILE2. DAT nebo to může znamenat "ignorovat FILE2". DAT a vytvořte b druhý popisovač souboru FILE1.DAT." Ke každé třídě musíte připojit odpovídající sémantiku kopírování, a to následujícím způsobem:

  • Použijte operátor operator= přiřazení, který vrací odkaz na typ třídy a přebírá jeden parametr předaný odkazem const – například ClassName& operator=(const ClassName& x);.

  • Použijte konstruktor kopírování.

Pokud nehlásíte konstruktor kopírování, kompilátor za vás vygeneruje konstruktor kopírování, který je moudrý člen. Podobně platí, že pokud nehlásíte operátor přiřazení kopírování, kompilátor za vás vygeneruje operátor přiřazení kopírování podle člena. Deklarace konstruktoru kopírování nepotlačí operátor přiřazení kopírování vygenerovaný kompilátorem a naopak. Pokud implementujete některou z nich, doporučujeme implementovat i druhou. Když implementujete obojí, význam kódu je jasný.

Konstruktor kopírování přebírá argument typu ClassName&, kde ClassName je název třídy. Příklad:

// spec1_copying_class_objects.cpp
class Window
{
public:
    Window( const Window& );            // Declare copy constructor.
    Window& operator=(const Window& x); // Declare copy assignment.
    // ...
};

int main()
{
}

Poznámka:

Kdykoli je to možné, nastavte typ argumentu const ClassName& konstruktoru kopírování. Tím zabráníte, aby konstruktor kopírování omylem změnil zkopírovaný objekt. Umožňuje také kopírovat z const objektů.

Konstruktory kopírování generované kompilátorem

Konstruktory kopírování generované kompilátorem, jako jsou konstruktory kopírování definované uživatelem, mají jeden argument typu "odkaz na název třídy". Výjimkou je, že všechny základní třídy a členské třídy mají konstruktory kopírování deklarované jako jeden argument názvu třídyconst>. V takovém případě je argument konstruktoru copy vygenerovaný kompilátorem také const.

Pokud typ argumentu pro konstruktor kopírování není const, inicializace zkopírováním objektu const vygeneruje chybu. Obrácená hodnota není pravdivá: Pokud argument je const, můžete inicializovat zkopírováním objektu, který není const.

Operátory přiřazení generované kompilátorem se řídí stejným vzorem pro const. Přebírají jeden argument typu ClassName& , pokud operátory přiřazení ve všech základních a členských třídách nemají argumenty typu const ClassName&. V tomto případě má vygenerovaný operátor přiřazení pro třídu const argument.

Poznámka:

Pokud jsou virtuální základní třídy inicializovány konstruktory kopírování, ať už generované kompilátorem nebo uživatelem definované, jsou inicializovány pouze jednou: v okamžiku, kdy jsou vytvořeny.

Důsledky jsou podobné konstruktoru kopírování. Pokud typ argumentu není const, přiřazení z objektu const vygeneruje chybu. Obrácená hodnota není pravdivá: Pokud const je hodnota přiřazená k hodnotě, která není const, přiřazení proběhne úspěšně.

Další informace o přetížených operátorech přiřazení naleznete v tématu Přiřazení.