2017-07-11 7 views
13

J'ai essayé de comprendre lvalue et rvalue en C++ 11. J'ai donc écrit un code de test:Pourquoi la liaison de référence rvalue à xvalue ne fonctionne pas dans mon code?

int x = 10; 
int foo() { return x; } 
int& bar() { return x; } 
int&& baz() { return 10; } 

int main() { 
    int& lr1 = 10;  // error: lvalue references rvalue 
    int& lr2 = x;  // ok 
    int& lr3 = foo(); // error: lvalue references rvalue 
    int& lr4 = bar(); // ok 
    int& lr5 = baz(); // error: lvalue references rvalue 

    int&& rr1 = 10; // ok 
    int&& rr2 = x;  // error: rvalue references lvalue 
    int&& rr3 = foo(); // ok 
    int&& rr4 = bar(); // error: rvalue references lvalue 
    int&& rr5 = baz(); // ok 
} 

Cela fonctionne très bien, j'ai donc inséré std :: cout pour imprimer les résultats.

#include <iostream> 

int x= 10; 
int foo() { return x; } 
int& bar() { return x; } 
int&& baz() { return 10; } 

int main() { 
    int& lr1 = 10;  std::cout << lr1 << std::endl; // error 
    int& lr2 = x;  std::cout << lr2 << std::endl; // ok 
    int& lr3 = foo(); std::cout << lr3 << std::endl; // error 
    int& lr4 = bar(); std::cout << lr4 << std::endl; // ok 
    int& lr5 = baz(); std::cout << lr5 << std::endl; // error 

    int&& rr1 = 10; std::cout << rr1 << std::endl; // ok 
    int&& rr2 = x;  std::cout << rr2 << std::endl; // error 
    int&& rr3 = foo(); std::cout << rr3 << std::endl; // ok 
    int&& rr4 = bar(); std::cout << rr4 << std::endl; // error 
    int&& rr5 = baz(); std::cout << rr5 << std::endl; // ERROR!? 
} 

int&& rr5 = baz(); std::cout << rr5; provoque une erreur d'exécution, mais je ne sais pas pourquoi il fait une erreur.

Je pense que la valeur de retour de baz() serait xvalue, donc sa durée de vie est prolongée. Mais quand j'ai essayé d'accéder à sa valeur, l'erreur se produit. Pourquoi?

+6

En posant les questions construire sur les erreurs, s'il vous plaît inclure l'erreur réelle (en pleine, complète, non édité, collé-copie sous forme de texte) dans le corps de question. –

+1

Oh désolé. Cela provoque une erreur d'exécution. –

+2

"xvalue donc c'est la vie est prolongée" ce serait une idée fausse. C++ prolonge les durées de vie des * temporaires *, et non des valeurs, des valeurs ou des prvalues. Il le fait lorsqu'une référence est liée à un tel objet temporaire. Il n'y a pas d'objet temporaire dans votre expression. De plus, 'bar' et' baz' invoquent tous deux un comportement indéfini, l'un renvoyant une référence à un objet local et l'autre ne renvoyant rien. –

Répondre

18

Je pense que la valeur de retour de baz() serait xvalue, donc sa durée de vie est prolongée.

Au début, ce qui renvoie baz() est toujours une référence pendante. Pour int&& baz() { return 10; }, le lifetime of the temporary n'est Il est construit à l'intérieur de la fonction et sera détruit à la sortie de la fonction, puis baz() renvoie toujours une référence qui pend.

Une liaison temporaire à une valeur de retour d'une fonction dans une instruction return n'est pas étendue: elle est immédiatement détruite à la fin de l'expression de retour. Une telle fonction renvoie toujours une référence qui pend.

Ensuite, pour int&& rr5 = baz();, rr5 est également une référence pendante; la déférence sur elle conduit à UB et tout est possible. D'autre part, si vous modifiez baz() pour revenir en valeur, tout ira bien; la valeur de retour est copiée puis liée à rr5, puis la durée de vie du temporaire est étendue à la durée de vie de rr5.

LIVE

+0

Ne devrait-il pas être sauvegardé dans 'rr5' avant que le temporaire ne soit détruit? – CinCout

+1

@CinCout Il devrait être 'déplacé' dans la fonction' baz() 'pour que cela fonctionne –

+3

@CinCout -' rr5' ne stocke rien. C'est lié à un objet. Cet objet est essentiellement détruit avant même que la liaison ne se produise. – StoryTeller