0Pricing
C++ Academy · Lekcja

Konstruktory przenoszące i przenoszące operatory przypisania

Poprawnie implementuj konstruktory przenoszące i przenoszące operatory przypisania

Konstruktory przenoszące i przenoszące operatory przypisania to bezpłatna lekcja C++ Academy na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C++ Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C++ Academy zawiera 4 lekcji w sumie.

Dwaj specjalni członkowie

konstruktor przenoszący i operator przypisania przenoszącego pozwalają klasie przejąć zasoby innej instancji bez ich kopiowania.

Sygnatura

Oba przyjmują referencję rvalue do tego samego typu.

class String {
public:
    String(String&& other) noexcept;          // move ctor
    String& operator=(String&& other) noexcept; // move assign
};

Implementowanie konstruktora przenoszącego

Należy przejąć zasoby źródła i pozostawić je w prawidłowym, pustym stanie.

String(String&& other) noexcept
    : data_(other.data_), size_(other.size_) {
    other.data_ = nullptr;
    other.size_ = 0;
}

Implementowanie operatora przypisania przenoszącego

Trzy kroki: zwolnić bieżące zasoby, przejąć zasoby źródła i pozostawić źródło puste.

String& operator=(String&& other) noexcept {
    if (this != &other) {
        delete[] data_;
        data_ = other.data_;
        size_ = other.size_;
        other.data_ = nullptr;
        other.size_ = 0;
    }
    return *this;
}

Dlaczego noexcept ma znaczenie

Operacje przenoszenia należy oznaczać jako noexcept, gdy tylko jest to możliwe. Kontenery standardowe, takie jak std::vector, używają przenoszenia podczas zmiany rozmiaru tylko wtedy, gdy jest ono oznaczone jako noexcept; w przeciwnym razie, aby zapewnić bezpieczeństwo wyjątków, korzystają z kopiowania.

Reguła pięciu

Jeśli napiszą Państwo którykolwiek z tych pięciu elementów, należy rozważyć wszystkie pięć:

  • destruktor
  • konstruktor kopiujący
  • operator przypisania kopiującego
  • konstruktor przenoszący
  • operator przypisania przenoszącego

Reguła zera

Jeszcze lepiej — nie pisać żadnego z nich. Należy przechowywać składowe jako typy RAII (wektory, napisy, inteligentne wskaźniki). Domyślne implementacje wygenerowane przez kompilator będą działać poprawnie i wydajnie.

class Widget {
    std::string name_;
    std::vector<int> data_;
    // No need for destructor, copy, or move — compiler does the right thing
};

Kiedy kompilator generuje operacje przenoszenia

Kompilator generuje domyślne funkcje przenoszące tylko wtedy, gdy:

  • użytkownik nie zadeklarował konstruktora kopiującego, operatora przypisania kopiującego, destruktora ani funkcji przenoszących
  • wszystkie składowe i klasy bazowe można samodzielnie przenosić

Domyślne i usunięte operacje przenoszenia

Można jawnie zażądać wygenerowania przez kompilator funkcji przenoszących lub zabronić ich generowania.

class Widget {
public:
    Widget(Widget&&) = default;
    Widget& operator=(Widget&&) = default;
    // or
    Widget(Widget&&) = delete;
};

Po przeniesieniu

Obiekt, z którego przeniesiono dane, znajduje się w stanie poprawnym, lecz nieokreślonym. Można:

  • zniszczyć go
  • przypisać mu nową wartość
  • wywołać dowolną operację, która nie ma warunku wstępnego (size(), empty(), clear())

Przypadki użycia

Semantyka przenoszenia przyspiesza:

  • zwracanie dużych obiektów (gdy RVO nie zadziała)
  • umieszczanie dużych obiektów w kontenerach (push_back dla r-wartości)
  • implementowanie własnych typów zarządzających zasobami

Szybkie sprawdzenie

Dlaczego konstruktory przenoszące i operatory przypisania przenoszącego powinny być oznaczane jako noexcept?

Podsumowanie

Konstruktory przenoszące i operatory przypisania przenoszącego przejmują zasoby od r-wartości, która wkrótce przestanie istnieć. Należy oznaczać je jako noexcept, aby przyspieszyć działanie kontenerów. Należy stosować regułę pięciu — a jeszcze lepiej regułę zera, składając typy ze standardowych typów RAII.

Często zadawane pytania

Czy lekcja „Konstruktory przenoszące i przenoszące operatory przypisania” jest bezpłatna?

Tak — pełny tekst „Konstruktory przenoszące i przenoszące operatory przypisania” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C++ Academy, przejdź na CoddyKit PRO. Kurs C++ Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Konstruktory przenoszące i przenoszące operatory przypisania”?

Poprawnie implementuj konstruktory przenoszące i przenoszące operatory przypisania Ćwiczysz C++ Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C++ Academy?

Nie wymagamy żadnego doświadczenia. C++ Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Konstruktory przenoszące i przenoszące operatory przypisania”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C++ Academy?

Tak. Każda lekcja C++ Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Lvalue a rvalue — różnica
  2. Referencje rvalue i składnia &&
  3. std::move i std::forward
  4. Konstruktory przenoszące i przenoszące operatory przypisania
← Powrót do C++ Academy