(Waarom) moet een verplaatsingsconstructor of verplaatsingstoewijzingsoperator zijn argument verduidelijken?

 C Programming >> C Programmeren >  >> Tags >> struct
(Waarom) moet een verplaatsingsconstructor of verplaatsingstoewijzingsoperator zijn argument verduidelijken?

Ze hebben niet nodig schoon te maken. De ontwerper van de klasse besloot dat het een goed idee zou zijn om het verplaatst-van-object nul geïnitialiseerd te laten.

Merk op dat een situatie waarin het zinvol is, is voor objecten die bronnen beheren die worden vrijgegeven in de destructor. Bijvoorbeeld een verwijzing naar dynamisch toegewezen geheugen. Als u de aanwijzer in het verplaatste-van-object ongewijzigd laat, betekent dit dat twee objecten dezelfde bron beheren. Hun beide vernietigers zouden proberen te bevrijden.


De auteur van de klas.

Als je kijkt naar de documentatie voor std::unique_ptr , zie je dat na de volgende regels:

std::unique_ptr<int> pi = std::make_unique<int>(5);
auto pi2 = std::move(pi);

pi is eigenlijk in een zeer gedefinieerde staat. Het zal zijn reset() . geweest en pi.get() zal gelijk zijn aan nullptr .


Je hebt zeer waarschijnlijk gelijk dat de auteur van deze klasse onnodige operaties in de constructor plaatst.

Zelfs als m_wheels waren een heap-toegewezen type, zoals std::vector , zou er nog steeds geen reden zijn om het te "wissen", aangezien het al is wordt doorgegeven aan zijn eigen move-constructor:

: m_wheels(std::move(ori.m_wheels)),   // invokes move-constructor of appropriate type

Je hebt echter niet genoeg van de klas laten zien om ons in staat te stellen weten of de expliciete "clearing"-operaties in dit specifieke geval nodig zijn. Volgens het antwoord van Deduplicator wordt verwacht dat de volgende functies zich correct gedragen in de staat "verplaatst van":

// Destruction
~Motorcycle(); // This is the REALLY important one, of course
// Assignment
operator=(const Motorcycle&);
operator=(Motorcycle&&);

Daarom moet u kijken naar de implementatie van elk van deze functies om te bepalen of de move-constructor correct is.

Als alle drie de standaardimplementatie gebruiken (die, van wat je hebt laten zien, redelijk lijkt), dan is er geen reden om de verplaatst-van-objecten handmatig te wissen. Als echter een van deze functies gebruiken de waarden van m_wheels , m_speed , of m_direction om te bepalen hoe zich te gedragen, dan kan de move-constructor nodig om ze te wissen om het juiste gedrag te garanderen.

Een dergelijk klassenontwerp zou onelegant en foutgevoelig zijn, aangezien we doorgaans niet zouden verwachten dat de waarden van primitieven van belang zijn in de "verplaatste" toestand, tenzij de primitieven expliciet worden gebruikt als vlaggen om aan te geven of opschonen moet plaatsvinden in de vernietiger.

Uiteindelijk, als voorbeeld voor gebruik in een C++-klasse is de getoonde move-constructor technisch niet "fout" in de zin van het veroorzaken van ongewenst gedrag, maar het lijkt een slecht voorbeeld omdat het waarschijnlijk precies de verwarring veroorzaakt die ertoe leidde dat je deze vraag postte.