Übergabe von rvalue als Referenz

7

Ich habe einen Qt Code, den ich von meinem Svn Repo heruntergeladen habe. Es ist eine Weile her, seit ich daran gearbeitet habe, aber ich bin mir sicher, dass es kompiliert hat.

Ich habe eine neue Version von Qt und Compiler (zu dem, was ich in der letzten Zeit hatte). Mein aktueller Compiler ist: mingw 4.9.2 32-bit.

Also hier ist mein Problemcode:

%Vor%

Wo:

%Vor%

und

%Vor%

Sie können also hier sehen, dass ich eine Funktion encodeData () habe, die einen Parameter uint8Vect_t & (pass by ref) übernimmt. Ich übergebe eine temporäre Variable (ein rvalue, die ich denke), die mit Hilfe des Konstruktors std :: vector (eines davon benötigt zwei Iteratoren) aus dem QByteArray dataBlock iterators (den ich getestet habe funktioniert) erstellt hat.

Allerdings bekomme ich den Fehler:

  

../ audioTest / txaudiostream.cpp: In der Mitgliedsfunktion 'void   CTxAudioStream :: playFile () ': ../audioTest/txaudiostream.cpp:212:94:   error: keine passende Funktion für den Aufruf von   "CTxAudioStream :: encodeData (uint8Vect_t)"                uint8Vect_t testVect = codierenDaten (uint8Vect_t (dataBlock.begin (), dataBlock.end ()));                                                                                                 ^ ../audioTest/txaudiostream.cpp:212:94: Anmerkung: Kandidat ist:   ../audioTest/txaudiostream.cpp:36:13: Hinweis: uint8Vect_t   CTxAudioStream :: encodeData (uint8Vect_t & amp;) uint8Vect_t   CTxAudioStream :: encodeData (uint8Vect_t & amp; dataBuff)                ^ ../audioTest/txaudiostream.cpp:36:13: Hinweis: keine bekannte Konvertierung für Argument 1 von 'uint8Vect_t {aka std :: vector}' zu 'uint8Vect_t & amp; {aka std :: vector & amp;} '

Grundsätzlich heißt es, dass ich nicht von uint8Vect_t in uint8Vect_t & amp; konvertieren kann. Aber wenn ich eine Variable vom Typ uint8Vect_t in die Funktion übergebe (und nicht den Rückgabewert der contructor / temp-Variablen), dann funktioniert das ok.

Ich dachte, in C ++ 11 könnt ihr Rvalues ​​weitergeben ... aber mir fehlt hier offensichtlich etwas. Kann mir jemand erklären:

  1. Warum ist das falsch?
  2. Was ist eine effiziente / elegante (lesbare) Lösung?
code_fodder 07.01.2016, 12:49
quelle

3 Antworten

11

Ihr Problem ist

%Vor%

Hier nehmen Sie Bezug auf ein uint8Vect_t . Das funktioniert gut mit normalen Variablen, aber uint8Vect_t(dataBlock.begin(), dataBlock.end()) ist ein temporäres Objekt und kann nicht an lvalue Referenz gebunden werden.

Wenn encodeData() dataBuff nicht ändert, dann ist die einfachste Lösung, ein const & zu nehmen, das an ein Temporary binden kann.

%Vor%

Wenn Sie den Inhalt von dataBuff ändern müssen, müssten Sie eine andere Version von encodeData() schreiben, die eine rvalue-Referenz

benötigt %Vor%

Dadurch kann der temporäre Vektor in die Funktion verschoben und dann in der Funktion wie in einem normalen Vektor bearbeitet werden

Ich glaube, der Grund dafür ist, dass Ihr alter Compiler eine Version von Microsoft Visual Studio war. MSVS verfügt standardmäßig über eine nicht standardmäßige Erweiterung, die es ermöglicht, dass temporäre Objekte an eine Lvalue-Referenz gebunden werden. Sie können mehr darüber lesen unter: Nicht-const Referenz gebunden an temporärer Visual Studio Bug?

Dies wird hinzugefügt, um Ihnen zu zeigen, wie Sie encodeData() ändern können, um eine Rvalue-Referenz zu nehmen, ohne eine neue Funktion schreiben zu müssen.

%Vor%

Live-Beispiel

Im obigen Beispiel ruft modify({ 1,2,3,4,5 }) modify(std::vector<int>&& foo) auf und ist dann in der Funktion foo kein Lvaue. Wir geben dann das Ergebnis der Übergabe des "neuen" zu korrigierenden Werts zurück (std :: vector & amp; foo), der dann einen modifizierten Vektor zurückgibt.

    
NathanOliver 07.01.2016, 12:59
quelle
6

Wenn Sie

verwenden %Vor%

Der Vektor, den Sie an die Funktion übergeben, ist ein temporäres Objekt, und Referenzen können nicht an temporäre Objekte gebunden werden.

Die einfache Lösung, wenn die Funktion das Argument nicht ändert, besteht darin, es zu einem Konstanten Objekt zu machen:

%Vor%

Verweise auf konstante Objekte können an temporäre Objekte gebunden werden.

    
Some programmer dude 07.01.2016 12:57
quelle
2

Was möchten Sie mit dem Objekt tun, das Sie übergeben?

Wenn du es als uint8Vect_t &dataBuff nimmst, sollte das bedeuten, dass du dauerhafte Änderungen daran vornehmen willst, was keinen Sinn macht, wenn es sich um ein temporäres handelt.

Wenn du es als uint8Vect_t const&dataBuff nimmst, sollte das bedeuten, dass du es kopieren und nicht verändern willst, was wahrscheinlich das ist, was du willst .

Wenn du es als uint8Vect_t dataBuff nimmst, solltest du deine eigene lokale temporäre Kopie davon haben, die du benutzen kannst, wie du es wünschst und dann wegwirfst, und das sollte wichtig genug sein, um die Kosten des Kopierens wert zu sein.

Wenn Sie es als uint8Vect_t &&dataBuff verwenden, sollte das bedeuten, dass Sie nicht dauerhafte Änderungen (z. B. das Stehlen von Inhalten) von einem temporären Objekt vornehmen möchten, das der Aufrufer nach dem Beenden des Vorgangs effektiv wegwerfen möchte.

Diese letzte Option ist die neue in C ++ 11 zum Übergeben von rvalues.

    
JSF 07.01.2016 12:56
quelle

Tags und Links