ProgrammatieC++ ontwikkelaar

Beschrijf de regels van drie en vijf (Rule of Three / Rule of Five) in C++11 en hun belang bij het ontwerpen van klassen.

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Regel van drie: als een klasse een bron beheert (bijvoorbeeld geheugen), dan moet bij expliciete implementatie van een van de volgende methoden ook de rest worden geïmplementeerd:

  • Destructeur
  • Kopieerconstructor
  • Kopieer toewijzingsoperator

C++11: Regel van vijf – zijn verplaatsingsoperaties toegevoegd:

  • Verplaatsingsconstructor
  • Verplaatsings toewijzingsoperator

Het schenden van deze regel leidt tot fouten in eigenaarschap van bronnen, zoals dubbele verwijdering of geheugenlekken.

Voorbeeldcode:

class Buffer { char* data; public: Buffer(size_t sz) : data(new char[sz]) {} ~Buffer() { delete[] data; } Buffer(const Buffer& other) : data(new char[strlen(other.data)+1]) { strcpy(data, other.data); } Buffer& operator=(const Buffer& other) { if (&other != this) { delete[] data; data = new char[strlen(other.data)+1]; strcpy(data, other.data); } return *this; } // move-semantiek in C++11+: Buffer(Buffer&& other) noexcept : data(other.data) { other.data = nullptr; } Buffer& operator=(Buffer&& other) noexcept { if (&other != this) { delete[] data; data = other.data; other.data = nullptr; } return *this; } };

Flauwe vraag.

Is het voldoende om alleen een destructeur te implementeren als de klasse een pointer beheert?

Nee. Zonder kopieer- en verplaatsingsoperaties zal er bij het kopiëren dubbele verwijdering van geheugen plaatsvinden. Bijvoorbeeld:

Buffer a(10); Buffer b = a; // b en a zullen dezelfde pointer verwijderen!

Voorbeelden van echte fouten door gebrek aan kennis over de details van het onderwerp.


Verhaal

In het dataverzamelplatform voor telecommunicatie implementeerde elke klasse alleen de destructeur. Na het refactoren van de structuur vond er een massale crash plaats door double free: het kopiëren van objecten veroorzaakte willekeurige gedragingen.


Verhaal

In een mobiel spelproject vergaten ze de move-constructor voor de containerklasse buffer te implementeren. Bij het verplaatsen werd het object gekopieerd, wat leidde tot onnodige gegevenskopieën en prestatieproblemen.


Verhaal

In de serialisatiebibliotheek van gegevensstructuren werd bij het retourneren van een object uit een functie een tijdelijk object geretourneerd, terwijl de kopieerconstructor een shallow copy van de pointer maakte. Dit leidde tot talrijke geheugenlekken, die pas maanden later zichtbaar werden.