2016-07-16 25 views
1
class MyClass { 
    public: 
     MyClass() 
     { 
      std::cout << "default constructor\n"; 
     } 
     MyClass(MyClass& a) 
     { 
      std::cout << "copy constructor\n"; 
     } 

     MyClass(MyClass&& b) 
     { 
      std::cout << "move constructor\n"; 
     } 
}; 

void test(MyClass&& temp) 
{ 
    MyClass a(MyClass{}); // calls MOVE constructor as expected 
    MyClass b(temp); // calls COPY constructor... not expected...? 
} 

int main() 
{ 
    test(MyClass{}); 
    return 0; 
} 

Für den obigen Code, erwartete ich beide Objekt Schöpfungen in Test() bewegen Konstruktor zu nennen, weil a b rvalue Referenztyp (MyClass & &) ist.C++ Konstruktor bewegen sich nicht für rvalue Referenz genannt

Die Übergabe von b an den MyClasss- Konstruktor ruft den move -Konstruktor jedoch nicht wie erwartet auf, sondern ruft stattdessen den Kopierkonstruktor auf.

Warum ruft der zweite Fall den Kopierkonstruktor auf, auch wenn das übergebene Argument vom Typ MyClass ist & & (r-Wert-Referenz) ???

Ich benutze gcc 5.2.1. Um meine Ergebnisse zu reproduzieren, müssen Sie die Option -fno-elide-constructors an gcc übergeben, um die Kopieroptimierung zu deaktivieren.


void test(MyClass&& temp) 
{ 
    if (std::is_rvalue_reference<decltype(temp)>::value) 
     std::cout << "temp is rvalue reference!!\n"; 
    else 
     std::cout << "temp is NOT rvalue!!\n"; 
} 

Above Code druckt "temp rvalue Referenz", auch wenn Temp gestattet.

Temp-Typ ist R-Wert Referenztyp.

+0

Ausdruck 'temp' zu einem L-Wert refernce auswertet, keine rvalue Referenz. Die Tatsache, dass Sie 'temp' als rvalue-Referenz deklariert haben, spielt keine Rolle. Eine * benannte * Referenz ist immer ein L-Wert. – AnT

+0

@AnT Haben Sie Referenzen in C++ - Standarddokumenten? Ich habe mich sehr bemüht, nach einem Hinweis auf diese Regel zu suchen, aber ich konnte keinen finden ... – SHH

+2

Siehe den Anfang von ** 5 Ausdrücke **. Es ist alles in 5/5, 5/6 und 5/7. Vgl. Insbesondere Note 5/7, die im Grunde genau das angibt. Auch das verlinkte "Duplikat" hat einen Link zu einem Artikel von Thomas Becker zum Thema. – AnT

Antwort

3
void test(MyClass&& temp) 
{ 
    MyClass a(MyClass{}); // calls MOVE constructor as expected 
    MyClass b(temp); // calls COPY constructor... not expected...? 
} 

denn das ist, temp (da es einen Namen hat,) ist ein lvalue Verweis auf ein rvalue. Um als rvalue an jedem beliebigen Punkt zu behandeln, rufen std::move

void test(MyClass&& temp) 
{ 
    MyClass a(MyClass{}); // calls MOVE constructor as expected 
    MyClass b(std::move(temp)); // calls MOVE constructor... :-) 
} 
+0

'ein L-Wert Verweis auf einen R-Wert' ... Wie kann R-Wert Lvalue-Referenz haben? Das ist jenseits meines Verständnisses. – Youda008