2017-11-25 3 views
2

Ich lerne zur Zeit C++ und wundere mich über die den man den richtigen Weg ist std zu verwenden ::Welcher Konstruktor löst die Umzugs-Semantik aus?

//Code might be incorrect since I havent tested it out 
Xyt::ByteArray* Xyt::ResourceManager::LoadFileToByteArray(std::string Path) 
{ 
try { 
    std::ifstream FileStream(Path, std::ios::in); 
    std::ifstream::pos_type Pos = FileStream.tellg(); 

    FileStream.seekg(0, std::ios::beg); 

    std::vector<char> Buff(Pos); 
    FileStream.read(Buff.data(), Pos); 

    FileStream.close(); 

    //I want to trigger the move constructor here 
    return new Xyt::ByteArray(std::move(Buff)); 
} 
catch (std::exception e) { 
    std::cout << "ERROR::FILE::FILE_NOT_SUCCESFULLY_READ" << Path << std::endl; 
    return nullptr; 
    } 
} 

bewegen, was ich bin verwirrt ist, welche die Bewegung Konstruktor für std :: auslösen Vektor?

Ist es dieses (kompilieren Fehler beim Anrufer doesnt Verwendung std :: move)

Xyt::ByteArray::ByteArray(std::vector<char>&& Buffer) 
{ 
    this->Buffer = Buffer; 
} 

dieses (beide std :: akzeptiert move (Buff) und Buff)?

Xyt::ByteArray::ByteArray(std::vector<char> Buffer) 
{ 
    this->Buffer = Buffer; 
} 

oder dieser?

Xyt::ByteArray::ByteArray(std::vector<char> Buffer) 
{ 
    this->Buffer = std::move(Buffer); 
} 

Mein Verständnis um das Internet aus der Lektüre, dass der erste Konstruktor der richtige Weg ist, um die Bewegung Semantik zu nutzen. Aber wenn ich den 1. Konstruktor benutze, muss ich einen anderen Konstruktor machen, wenn ich eine Kopie auf dem std :: vector Buff machen will?

Jede Hilfe wäre willkommen!

Antwort

2

Der einzige, der funktioniert, ist der dritte. Aber das ist, weil Sie std::moveinnerhalb des Konstruktors verwendet haben. Und es provoziert zwei Züge: einen zum Ausfüllen des Parameters und einen von dem Parameter in den Wert.

Der richtige Weg, dies zu tun ist:

Xyt::ByteArray::ByteArray(std::vector<char>&& Buf) 
    : Buffer(std::move(Buf)) 
{} 

Das ruft nur den einmal Verschiebevorgang.

Sie müssen explizit von benannten Rvalue-Referenzen wechseln, wenn Sie eine Verschiebeoperation aufrufen möchten.


Aber wenn ich den ersten Konstruktor bedeutet, dass ich einen anderen Konstruktor machen müssen, wenn ich tatsächlich eine Kopie möchte auf dem std :: vector Buff tun?

Sie müssen nicht unbedingt. Sie könnten Benutzer benötigen das Kopieren selbst tun, wenn sie die Funktion aufrufen:

Xyt::ByteArray(std::vector<char>(Buff)) 

Aber ja, wenn Benutzer direkt einen L-Wert zur Verfügung zu stellen, und Sie möchten von der L-Wert kopieren, dann müssen Sie ein schaffen Konstruktor, der eine lvalreferenz (const) übernimmt und eine Kopie ausführt.

+0

Ich denke, ich verstehe es. Eine weitere Sache jedoch, Xyt :: ByteArray :: ByteArray (Std :: Vektor & Puffer) { this-> Puffer = Std :: move (Buffer); }, Wenn sich ein std :: so bewegt, würde dies den move -Konstruktor zweimal aufrufen, ähnlich wie beim dritten Konstruktor? – Xyten

+1

@Xyten: Nein. Der move * -Konstruktor * wird überhaupt nicht aufgerufen. Es wird move * assignment * aufgerufen, da 'ByteArray :: Buffer' an diesem Punkt ein * Live-Objekt * ist. Deshalb habe ich den Memberinitialisierer verwendet; das ist, wo Sie * Initialisierung * von Mitgliedern setzen. –

Verwandte Themen