2016-05-31 26 views
-3

Wenn ich den folgenden Code:Warum akzeptieren die C++ - Standardbibliotheksoperatoren rvalues?

std::string myString = "I'm a string."; 
const std::string::iterator &myIterator = ++myString.begin(); 
char c = *myIterator; 
std::cout << c << std::endl; 

ich einen Segmentation Fault erhalten (mit O3 Optimierung kompilieren). Ich nehme an, das liegt daran, dass der Operator ++ einen std::string::iterator & statt std::string::iterator zurückgibt, und so erhalten wir einen Verweis auf eine temporäre. Gibt es einen Grund, warum dies nicht implementiert ist, um einen Kompilierungsfehler zu verursachen? D.h. warum ist die Unterschrift nicht die folgende?

std::string::iterator &std::string::iterator::operator++() &; 

Oder noch besser, warum erfordert nicht die Spezifikation die folgenden Signaturen, so dass wir rvalues ​​ohne Probleme umgehen kann?

std::string::iterator &std::string::iterator::operator++() &; 
std::string::iterator std::string::iterator::operator++() &&; 
+4

[Kann nicht reproduziert werden] (https://ideone.com/I9Z8De). Bist du sicher, dass es an diesen Zeilen liegt? Nebenbei bemerkt, selbst wenn '++' eine Referenz zurückgibt, ist 'myIterator' keine Referenz, so dass es den Wert – Rakete1111

+3

kopiert. Das funktioniert gut. Können Sie vollständigen Code posten? – Sumeet

+0

Ja, Sie haben Recht. Ich habe das Beispiel geändert und es sollte jetzt abstürzen. –

Antwort

0

Der Code, den Sie geschrieben haben mir legal aussieht: std::string::iterator myIterator = ++myString.begin();Kopien der Iterator Verweis in myIterator so gibt es keine baumelnden Verweise auf Provisorien.

Meine psychischen Debuggen Kräfte mir sagen, dass Ihre eigentliche Code einer von zwei Probleme:

  • Ihre Zeichenfolge tatsächlich leer ist, auch wenn Sie denken, dass es Text in ihm hat. In diesem Fall ist ++begin() ungültig.
  • Sie mutieren die Zeichenfolge nach Sie erhalten die Iterator-Kopie in einer Weise, die den Iterator ungültig macht.
+0

Meine psychische Vorhersage ist, dass das Codebeispiel "std :: string :: iterator & myIterator = ++ myString.begin();" sein sollte, in diesem Fall gibt es tatsächlich ein Dangling Referenz. –

+0

Guter Anruf (obwohl ich ursprünglich auch eine "const" hatte). Ich bin mir aber immer noch nicht sicher, warum dies erfolgreich kompiliert werden sollte. –

0

@ M.M Kommentare sind aufschlussreich. Insbesondere würde mein zweiter Vorschlag die Optionen der Bibliotheken bei der Implementierung von Iteratoren einschränken, da Iteratoren nicht inkrementierbar sein müssen als rvalues ​​(Referenz: http://en.cppreference.com/w/cpp/iterator/next), und tatsächlich könnte std :: string :: iterator als char * implementiert werden, was nicht als rvalue inkrementierbar ist. Die Wahl, ob mein erster Vorschlag befolgt wird, scheint eine Bibliotheksumsetzungsentscheidung zu sein, da der Standard vorschreibt, was Iteratoren können, nicht was sie nicht können, um nicht unnötig einzuschränken, welche Typen als Iteratoren funktionieren können. Natürlich könnte die Änderung der Implementierung zu diesem Zeitpunkt zu Änderungen bei den Benutzercodes führen.