Ok, std :: getline () mit einem moved-from std :: string zu verwenden?

8

Ist das zweite Argument für std::getline(std::istream&, std::string&) sicher und gut definiert? Ein L-Wert, der sich auf eine verschobene std::string bezieht, und, falls dies der Fall ist, wird diese Zeichenfolge wiederhergestellt Ist der Status "Moved-from" (Ausgezogen) aktiviert, sodass Methoden wie pop_back() sicher aufgerufen werden können?

Vereinfacht gesagt: Hat das Schreiben in eine Zeichenkette mit getline() eine äquivalente Semantik, um diese Zeichenkette zuzuweisen?

Oder ist das folgende (etwas erfundene) Snippet wohldefiniert und korrekt?

%Vor%

Optimierte ( -march=native -O3 ) Builds dieses Snippets mit g++ und clang++ scheinen wie erwartet zu funktionieren, aber das ist natürlich keine Garantie.

Ich würde gerne wissen, ob dies nur auf wohldefiniertes Verhalten gemäß der Semantik von getline() im C ++ 11-Standard beruht, oder, falls nicht, wenn es durch eine spätere Ausgabe von. gut definiert ist der Standard, oder, wenn nicht, wenn er zumindest explizit durch eine oder alle der wichtigsten Implementierungen definiert ist (G ++, Clang ++, Visual C ++, Intel C ++ Compiler).

Hinweis: Dies ist nicht ein Duplikat früherer Fragen, in dem gefragt wird, ob es sicher ist, einem verschobenen Objekt zuzuweisen (ja, wenn es ein Trivial- oder STL-Typ ist) Weil getline() nicht der Zuweisungsoperator ist.

    
Ray Hamel 10.10.2017, 18:27
quelle

3 Antworten

8

Ihr Code ist sicher, aber nur, weil Sie überprüfen, ob getline erfolgreich etwas in s gespeichert hat. Wenn die interne Sentry von getline nicht initialisiert werden konnte, wurde s nichts zugewiesen und sie würde im Status "valid-but-unspezifiziert" verbleiben. Solange getline erfolgreich s auf einen bekannten Status setzt, ist es gut.

Und das allererste, was getline nach erfolgreicher Sentry-Konstruktion tut, ist s auf eine Größe von Null (ein bekannter Zustand) zu setzen.

Mehr Details unten in GManNickG Kommentar.

    
Howard Hinnant 10.10.2017 18:55
quelle
5
  

Ist es sicher und wohldefiniert für das zweite Argument, dass std::getline(std::istream&, std::string&) ein lvalue ist, der auf eine verschobene from std::string

verweist?

Ja. Obwohl es die verschobene Zeichenfolge ist, wird sie vom Standard gemäß [string.cons] p2 nicht angegeben :

  

[...]. In der zweiten Form bleibt str in einem gültigen Zustand mit einem unspezifizierten Wert.

Die Zeichenfolge ist immer noch in einem gültigen Zustand, sie ist nur unspezifiziert, d. h. Sie können nicht wissen, in welchem ​​Zustand sie sich befindet (sie kann mit einigen zufälligen Zeichen gefüllt sein). Sie können es weiterhin an std::getline übergeben, da der Standard in [string.io] p1 Das str.erase() wird für die Zeichenfolge aufgerufen, die es leert:

  

[...] ruft str.erase() [...]

auf

(wenn der Stream gültig ist, aber ich nehme an, dass dies in Ihrem Fall ist).

Egal was der nicht spezifizierte Zustand des Strings ist, er wird am Anfang von std::getline geleert, es spielt also keine Rolle, in welchem ​​Zustand er sich befindet.

    
Rakete1111 10.10.2017 18:33
quelle
1

Eine Zugzuweisung oder eine Bewegung c'tor sollte das bewegte Objekt immer in einem gültigen Zustand belassen.

Im Falle einer std :: string bleibt%% co_de eine gültige, aber nicht spezifizierte Zeichenkette. Aus der Quelle von libc ++:

%Vor%

Und da std::move nur Zeichen an die Zeichenkette anhängt, so lange wie es erfolgreich ist, wird die Ausgabe wie erwartet sein. Von craplus.com :

  

Beachten Sie, dass jeder Inhalt in str vor dem Aufruf durch die neu extrahierte Sequenz ersetzt wird.

     

Jedes extrahierte Zeichen wird an die Zeichenkette angehängt, als ob sein Element push_back aufgerufen wurde.

    
Daniel Trugman 10.10.2017 18:42
quelle

Tags und Links