Eine häufige Falle in C++ Bewerbungsgesprächen

Eine häufige Falle in C++ Bewerbungsgesprächen

Bist du in C++ sattelfest genug, um bei einer Bewerbung eine Frage zu klären, die von der überwiegenden Mehrheit der Kandidaten nicht durchschaut wird? Wie wir alle wissen, verändert sich die gesamte IT-Welt und all die ausgefallenen Technologien, die wir täglich verwenden, sehr schnell. Das gilt auch für Programmiersprachen wie C++, die sich seit 2011 ziemlich schnell weiterentwickelt hat.

Der C++ 17-Standard wird derzeit in verschiedenen Produktionsumgebungen häufig verwendet, frühere Versionen sind aber durchaus auch noch gängig. Daher ist es keine Überraschung, dass IT-Recruiter Schwierigkeiten haben, zu überprüfen, ob alle Bewerber auch wirklich alle Vor- und Nachteile der oben genannten Standards kennen. Okay, aber kommen wir jetzt zur Sache!

Move Semantik wird als eine der wichtigsten in C++ 11 eingeführten Funktionalitäten angesehen. Eine einfache, aber sehr interessante Frage welche zu diesem Thema gern bei Bewerbungsgesprächen vorkommt:

„Was ist Move Semantik - was macht die Methode std::move?“

Und dies ist der Moment wo die Party losgeht. Die überwiegende Mehrheit der Kandidaten beginnt ihre Antworten mit:

„Es verschiebt zugrunde liegenden Speicher oder Referenz-Pointer von einem Objekt zu einem anderen... "

Diese Antwort kann man – je nachdem wie genau nachgefragt wird – einer Dichtheitsprüfung anhand eines Beispiels unterziehen:

std::vector< int > vec{1,2,3,4,5};

auto mvec = std::move(vec);

std::cout << vec.size() << std::endl;

std::cout << mvec.size() << std::endl;

Sieht nach einem recht einfacher Code aus - ein Vektor mit fünf Ints, zum Schluss zwei Zeilen zur Ausgabe, dann noch eine Zeile mit std::move zur Ergänzung. Aber jetzt kommen die hinterlistigen Fragen:

„Wird der Code kompiliert?“

Meist dann voller Hoffnung die Antwort:

„Ja klar, es wird kompiliert!“

Aye aye Captain Obvious, der Code wird tatsächlich kompiliert. Aber dann geht es weiter:

„Funktioniert der Code auch wie vorgesehen?“

Dies ist der Moment, in dem eine Bewerber-Augenbraue hochgezogen wird und langsam Zweifel auftauchen. Die meisten denken sich wahrscheinlich „Ich habe vor zwei Sätzen gesagt, dass Speicher oder Referenz-Pointer verschoben werden, also wird die die vec Variable invalid.“ Aber dann kommt gleich die nächste heimtückische Frage:

„Aber der Stack-Memory wird wohl kaum invalid sein?“

Nach so viel Nachbohren werfen viele Leute einfach das Handtuch, da sie keine andere Vorstellung von der möglichen Lösung im Kopf haben. Anscheinend dachten sie, sie wüssten ungefähr wie der berüchtigte std::move Befehl funktioniert, aber scheinbar haben sie keine Ahnung was hier überhaupt geschieht.

Keine Sorge! Hier findet man die Antwort, dass man beim nächsten Bewerbungsgespräch nicht in die gleiche Falle tappt.

std::move ist eine remove-reference-cast-to-rvalue Operation. Im Grunde wird sichergestellt, dass der Move Konstruktor – sofern dieser auf der linken Seite vorhanden ist – mit dem Argument von der rechten Seite aufgerufen wird. So einfach ist das.

Für unser Beispiel heißt das: Der Move Konstruktur der Variable mvec wird mit der Variablen vec als Argument aufgerufen. Move „stiehlt“ die internen Memory Objects, da der Vektor im Inneren aus drei Pointern besteht:

  • _M_start, ist nullptr
  • _M_finish, ist nullptr
  • _M_end_of_storage, ist nullptr

Moment mal, aber bedeutet nun „stehlen“? Der Move Konstruktor tut nun folgendes:

Die Daten werden getauscht (nicht zugewiesen, nicht kopiert, sondern vertauscht). Dies ist der schnellste und effizienteste Weg. Somit wird der alte Vektor vec leer sein und der neue Vektor mvec enthält nun die Elemente aus dem ursprünglichen vec. Aus diesem Grund funktioniert die Deallocation beider Vektoren so, als ob die ordnungsgemäß zugewiesenen Zeiger nur an einer Stelle vorhanden wären.

Verstanden? In Wahrheit ist es ja eine ganz einfache Antwort, kein Grund sich von den hinterlistigen Fragen zu viel verunsichern zu lassen ;)

Technologien in diesem Artikel