Udostępnij przez


Konstruktory kopiowania i operatory przypisania kopiowania (C++)

Uwaga

Począwszy od języka C++11, w języku obsługiwane są dwa rodzaje przypisania: przypisywanie kopii i przenoszenie przypisania. W tym artykule "przypisanie" oznacza przypisanie kopiowania, chyba że jawnie określono inaczej. Aby uzyskać informacje o przypisaniu przenoszenia, zobacz Move Constructors and Move Assignment Operators (C++)( Przenoszenie konstruktorów i operatorów przypisania przenoszenia (C++).

Zarówno operacja przypisania, jak i operacja inicjowania powodują skopiowanie obiektów.

  • Przypisanie: gdy wartość jednego obiektu jest przypisywana do innego obiektu, pierwszy obiekt jest kopiowany do drugiego obiektu. W związku z tym ten kod kopiuje wartość b do aelementu :

    Point a, b;
    ...
    a = b;
    
  • Inicjowanie: inicjowanie występuje podczas deklarowania nowego obiektu, przekazywania argumentów funkcji według wartości lub zwracania przez wartość z funkcji.

Semantyka "copy" można zdefiniować dla obiektów typu klasy. Na przykład, rozważmy ten kod:

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

Powyższy kod może oznaczać "skopiowanie zawartości pliku FILE1. DAT do FILE2. DAT" lub może to oznaczać "ignorować PLIK2. DAT i utwórz b drugą dojście do pliku FILE1.DAT". Należy dołączyć odpowiednią semantyka kopiowania do każdej klasy w następujący sposób:

  • Użyj operatora operator= przypisania, który zwraca odwołanie do typu klasy i przyjmuje jeden parametr przekazywany przez const odwołanie — na przykład ClassName& operator=(const ClassName& x);.

  • Użyj konstruktora kopiowania.

Jeśli konstruktor kopiujący nie zostanie zadeklarowany, kompilator wygeneruje konstruktor kopiujący mądry elementu członkowskiego. Podobnie, jeśli operator przypisania kopiowania nie zostanie zadeklarowany, kompilator wygeneruje operator przypisania kopiowania mądrego elementu członkowskiego. Deklarowanie konstruktora kopiowania nie pomija operatora przypisania kopiowania generowanego przez kompilator i odwrotnie. Jeśli zaimplementujesz jedną z nich, zalecamy również zaimplementowanie drugiej. Podczas implementowania obu tych elementów znaczenie kodu jest jasne.

Konstruktor kopiowania przyjmuje argument typu ClassName&, gdzie ClassName jest nazwą klasy. Na przykład:

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

int main()
{
}

Uwaga

Ustaw typ argumentu const ClassName& konstruktora kopiowania, jeśli jest to możliwe. Zapobiega to przypadkowej zmianie skopiowanego obiektu przez konstruktora kopiowania. Umożliwia również kopiowanie z const obiektów.

Konstruktory kopii wygenerowane przez kompilator

Konstruktory kopiowania generowane przez kompilator, takie jak konstruktory kopiowania zdefiniowane przez użytkownika, mają jeden argument typu "odwołanie do nazwy klasy". Wyjątek występuje, gdy wszystkie klasy bazowe i klasy składowe mają konstruktory kopii zadeklarowane jako przyjmujący jeden argument nazwy-klasy typuconst&. W takim przypadku argument konstruktora kopiowania wygenerowanego przez kompilator jest również const.

Gdy typ argumentu do konstruktora kopiowania nie constjest , inicjalizacja przez skopiowanie const obiektu generuje błąd. Odwrotnie nie ma wartości true: jeśli argument to const, można zainicjować, kopiując obiekt, który nie constjest .

Operatory przypisania generowane przez kompilator są zgodne z tym samym wzorcem dla elementu const. Przyjmują jeden argument typu ClassName& , chyba że operatory przypisania we wszystkich klasach bazowych i składowych przyjmują argumenty typu const ClassName&. W tym przypadku wygenerowany operator przypisania dla klasy przyjmuje const argument.

Uwaga

Gdy wirtualne klasy bazowe są inicjowane przez konstruktory kopii, niezależnie od tego, czy są generowane przez kompilator, czy zdefiniowane przez użytkownika, są inicjowane tylko raz: w momencie ich konstruowania.

Implikacje są podobne do konstruktora kopiowania. Gdy typ argumentu nie constjest , przypisanie z const obiektu generuje błąd. Odwrotnie nie ma wartości true: jeśli const wartość jest przypisana do wartości, która nie constjest , przypisanie powiedzie się.

Aby uzyskać więcej informacji na temat przeciążonych operatorów przypisania, zobacz Przypisywanie.