Reguła trzech/pięciu
Poprawnie zarządzaj kopiowaniem i przenoszeniem
Reguła trzech/pięciu to bezpłatna lekcja C++ Academy na CoddyKit. To lekcja 3 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.
Reguła trzech
Jeśli klasa wymaga własnego destruktora, niemal zawsze wymaga również własnego konstruktora kopiującego i operatora przypisania kopiującego. Te trzy elementy występują razem.
Dlaczego trzy
Klasa zarządzająca surowym zasobem musi określać sposób jego niszczenia, kopiowania i przypisywania — w przeciwnym razie płytkie kopie generowane przez kompilator prowadzą do podwójnego zwalniania.
#include <iostream>
class Bad {
int* p;
public:
Bad(int v) : p(new int(v)) {}
~Bad() { delete p; }
// default copy => two objects delete the same p!
};Niestandardowy konstruktor kopiujący
Prawidłowy konstruktor kopiujący wykonuje głęboką kopię, alokując własny zasób zamiast go współdzielić.
#include <iostream>
class Box {
int* p;
public:
Box(int v) : p(new int(v)) {}
Box(const Box& o) : p(new int(*o.p)) {} // deep copy
~Box() { delete p; }
int get() const { return *p; }
};
int main() {
Box a(5);
Box b = a; // independent copy
std::cout << b.get() << "\n";
}Niestandardowy operator przypisania kopiującego
Przypisanie kopiujące musi zwolnić stary zasób, zabezpieczyć się przed przypisaniem do samego siebie i wykonać głęboką kopię nowej wartości.
Box& operator=(const Box& o) {
if (this != &o) { // self-assignment guard
delete p;
p = new int(*o.p);
}
return *this;
}Reguła pięciu
C++11 dodaje operacje przenoszenia. Jeśli zdefiniują Państwo dowolną z pięciu funkcji (destruktor, konstruktor kopiujący, przypisanie kopiujące, konstruktor przenoszący, przypisanie przenoszące), należy rozważyć zdefiniowanie wszystkich pięciu.
Konstruktor przenoszący
Konstruktor przenoszący przejmuje zasób z obiektu tymczasowego i pozostawia źródło puste — jest to znacznie tańsze niż kopiowanie.
Box(Box&& o) noexcept : p(o.p) {
o.p = nullptr; // source left empty
}Przypisanie przenoszące
Przypisanie przenoszące zwalnia bieżący zasób, a następnie przejmuje własność zasobu źródłowego.
Box& operator=(Box&& o) noexcept {
if (this != &o) {
delete p;
p = o.p;
o.p = nullptr;
}
return *this;
}Oznaczanie operacji przenoszenia jako noexcept
Operacje przenoszenia powinny być oznaczone jako noexcept, aby kontenery takie jak std::vector mogły bezpiecznie ich używać podczas realokacji.
Reguła zera
Najlepiej jednak nie zarządzać bezpośrednio żadnymi surowymi zasobami. Korzystając z std::unique_ptr, std::vector lub std::string, mogą Państwo nie definiować żadnej z pięciu funkcji — domyślne implementacje kompilatora są prawidłowe.
#include <memory>
class Good {
std::unique_ptr<int> p; // owns the resource for you
public:
Good(int v) : p(std::make_unique<int>(v)) {}
// no destructor, no copy/move needed
};Usuwanie operacji
Jeśli kopiowanie nie ma sensu, należy je usunąć: Box(const Box&) = delete;. Dzięki temu typ jest celowo przenoszalny, ale niekopiowalny, albo całkowicie niekopiowalny.
Wybór właściwej reguły
Należy dążyć do stosowania reguły zera. Po regułę pięciu należy sięgać tylko wtedy, gdy rzeczywiście opakowują Państwo surowy zasób, którego nie obsługuje biblioteka standardowa.
Szybkie sprawdzenie
Proszę sprawdzić swoją znajomość reguły trzech/pięciu.
Podsumowanie
Poznali Państwo regułę trzech/pięciu: zarządzanie surowym zasobem wymaga spójnego zdefiniowania destruktora oraz operacji kopiowania i przenoszenia. Operacje przenoszenia należy oznaczać jako noexcept. Najlepiej jednak stosować regułę zera, korzystając ze standardowych typów RAII i nie definiując żadnej z tych funkcji.
Ucz się C++ dzięki korepetycjom AI — za darmo
Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.
- Kursy
- 51
- Lekcje
- 203
Często zadawane pytania
Czy lekcja „Reguła trzech/pięciu” jest bezpłatna?
Tak — pełny tekst „Reguła trzech/pięciu” 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 „Reguła trzech/pięciu”?
Poprawnie zarządzaj kopiowaniem i przenoszeniem Ć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 3 z 4.
Ile czasu zajmuje lekcja „Reguła trzech/pięciu”?
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
- Zasada RAII
- Destruktory i sprzątanie
- Reguła trzech/pięciu
- Strażnicy zakresu