ProgrammatieC++ ontwikkelaar

Wat gebeurt er bij het doorgeven van een object van een klasse per waarde aan een functie, en welke valkuilen moeten in overweging worden genomen bij de implementatie van een kopieerconstructor?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord

Bij het doorgeven van een object per waarde aan een functie in C++ vindt er een kopie van het object plaats met behulp van de kopieerconstructor. Als er een gebruikersgedefinieerde kopieerconstructor in de klasse is gedefinieerd, wordt deze aangeroepen om het tijdelijke argumentobject van de functie te initialiseren. Als er geen is gedefinieerd, wordt de standaard compiler gebruikt, die een bit voor bit kopieert (shallow copy).

Valkuilen:

  • Als de klasse resources beheert (bijvoorbeeld ruwe pointers heeft), zal de standaard gegenereerde kopieerconstructor resulteren in fouten van dubbele vrijgave van geheugen en lekken.
  • Zorg ervoor dat de kopieerconstructor resources correct kopieert (meestal deep copy).

Voorbeeld:

class StringWrapper { char* data; public: StringWrapper(const char* str) { data = new char[strlen(str) + 1]; strcpy(data, str); } // Fout: shallow copy StringWrapper(const StringWrapper& other) : data(other.data) {} ~StringWrapper() { delete [] data; } }; void foo(StringWrapper s) { // ... } int main() { StringWrapper s1("hello"); foo(s1); // UB!!! return 0; }

Misleidende vraag

"Wat gebeurt er als je de kopieerconstructor in een klasse met een pointer als volgt definieert: MyClass(const MyClass &other) : data(other.data) {}? Welke gevolgen heeft dit?"

Juiste antwoord: Deze kopieerconstructor zal een object creëren met een pointer naar hetzelfde geheugen als het gekopieerde. Bij vernietiging van de twee objecten zal het geheugen twee keer worden vrijgegeven (double free), wat leidt tot onbepaald gedrag. Er moet een deep copy worden geïmplementeerd:

MyClass(const MyClass &other) { data = new int(*other.data); }

Voorbeelden van echte fouten door gebrek aan kennis van de nuances van het thema


Verhaal

In een groot serverproject werden containers met objecten met een "ruwe" array erin gebruikt en de standaard kopieerconstructor (shallow copy). Bij het doorgeven van objecten per waarde trad double free op en crashten de applicaties, wat alleen in productie werd opgemerkt.


Verhaal

In een oude C++-bibliotheek voor het werken met afbeeldingen kopieerde de kopieerconstructor de grafische buffer niet, wat leidde tot het veranderen van één kopie van de afbeelding bij het veranderen van een andere en onverwachte bugs in de interface.


Verhaal

Bij het retourneren van een object per waarde uit een functie in een van de interne wachtwoordopslagsystemen werden de gegevens gewist bij vernietiging van het tijdelijke object (shallow copy), waardoor het echte object een gewiste pointer bevatte, en het lek toevallig tijdens een beveiligingsaudit werd ontdekt.