2016-01-27 2 views
4

Pourquoi l'objet que je passe à ClassA considère-t-il un rvalue (temporaire)? Je suis conscient que le réglage du paramètre à const fera disparaître l'erreur, mais je veux comprendre ce qui se passe.Pourquoi cet objet est-il considéré comme une valeur?

Ce comportement fonctionne correctement pour un appel de fonction mais pas pour un constructeur?

#include <iostream> 

using namespace std; 

class ClassA { 
public: 
    ClassA() {} 
    ClassA(ClassA&) {} 
}; 

void f(ClassA&) {} 

int main() { 
    ClassA a; 

    // Invalid initialization of non-const reference of type 'ClassA&' from an 
    // rvalue of type 'ClassA' 
    ClassA b = ClassA(a); 

    // Works fine 
    f(a); 

    return 0; 
} 
+0

'f (ClassA (a))' est également invalide. – cpplearner

Répondre

10

La valeur ici est l'expression ClassA(a).

ClassA b = ClassA(a); 

C'est la copie de l'initialisation, il tentera d'appeler le constructeur de copie de ClassA avec le résultat de ClassA(a), qui est un rvalue. Vous avez déclaré le constructeur de copie à prendre un ClassA&, qui ne peut pas lier à rvalues, de sorte que vous obtenez une erreur.

La meilleure solution est, comme vous le soulignez, d'ajouter const au constructeur de copie afin qu'il puisse se lier à rvalues, mais vous pouvez également utiliser-initialisation directe ou copier-initialisation sans conversion de type:

ClassA b (a); 
ClassA b {a}; //C++11 
ClassA b = a; 

Notez que bien que ClassA b = ClassA(a); nécessite une copie constructeur valide, la copie sera probablement elided. Ceci est actuellement facultatif, mais peut être fait mandatory à un moment donné.

+0

'ClassA b = a;' Fonctionne également, et est également copy-construction. – sp2danny