Move semantics is een C++ mechanisme dat het mogelijk maakt om bronnen efficiënt tussen objecten te verplaatsen in plaats van ze te kopiëren. Met de komst van C++11 zijn verplaatsende constructeurs en toewijzingsoperatoren geïntroduceerd, die objecten in staat stellen hun bronnen aan een ander object over te dragen zonder kopieerkosten.
std::move verandert het doorgegeven object in een rvalue-referentie, wat aangeeft dat de bronnen veilig kunnen worden verplaatst. std::forward wordt in sjablonen gebruikt om het type van de waarde (lvalue/rvalue) te behouden bij verdere overdracht.
#include <string> #include <vector> #include <iostream> std::vector<std::string> getNames() { std::vector<std::string> v = {"Alice", "Bob", "Charlie"}; return v; // Hier wordt move semantics geactiveerd } int main() { std::vector<std::string> names = getNames(); // Hier worden de contents van getNames() verplaatst zonder extra kopiëren }
Wat is het verschil tussen std::move en een bewegende constructor? Als je std::move schrijft, wordt het object dan altijd verplaatst?
Antwoord:
std::move is slechts een cast naar een rvalue-referentie, het voert op zichzelf geen verplaatsing uit. De verplaatsingsoperatie zal alleen plaatsvinden als er daadwerkelijk een geïmplementeerde move-constructor/operator is. Anders vindt er een kopie plaats.
struct A { A() = default; // geen move-constructor A(const A&) { std::cout << "Kopie! "; } }; A a1; A a2 = std::move(a1); // Kopie wordt aangeroepen, geen verplaatsing
Geschiedenis
-In een van de financiële systemen werd de werking met strings geoptimaliseerd door kopieën te vervangen door std::move, maar de structuur had geen geïmplementeerde move-constructors. Kopieën bleven bestaan, de prestaties stegen niet, wat leidde tot een valse zekerheid over de versnelling van de code.
Geschiedenis
-Een ontwikkelaar voerde std::move() uit op een variabele, die hij daarna bleef gebruiken na de verplaatsing. Gegevens kwamen in een inconsistente toestand, de applicatie crasht soms.
Geschiedenis
-In de server-bibliotheeuscodes accepteerden ze tijdelijke objecten via const-referentie, en probeerden toen std::move(), in de verwachting dat er een verplaatsing zou plaatsvinden. Het resultaat was kopiëren, inefficiëntie en verhoogde latentie onder zware belasting.