C ++: la valeur de retour est-elle une valeur L?

Considérez ce code:

struct foo { int a; }; foo q() { foo f; fa =4; return f;} int main() { foo i; ia = 5; q() = i; } 

Aucun compilateur ne s’en plaint, même Clang. Pourquoi q() = ... ligne est correcte?

Non, la valeur de retour d’une fonction est une valeur l si et seulement si c’est une référence (C ++ 03). (5.2.2 [expr.call] / 10)

Si le type renvoyé était un type de base, cela constituerait une erreur de compilation. (5.17 [expr.ass] / 1)

La raison pour laquelle cela fonctionne est que vous êtes autorisé à appeler des fonctions membres (même des fonctions non const ) sur des valeurs r de type classe et que l’atsortingbution de foo est une fonction membre définie par l’implémentation: foo& foo::operator=(const foo&) . Les ressortingctions pour les opérateurs de l’article 5 ne s’appliquent qu’aux opérateurs intégrés , (5 [expr] / 3), si la résolution de la surcharge sélectionne un appel de fonction surchargé pour un opérateur, les ressortingctions pour cet appel de fonction s’appliquent à la place.

C’est pourquoi il est parfois recommandé de renvoyer des objects de type classe en tant qu’objects const (par exemple, const foo q(); ), mais cela peut avoir un impact négatif en C ++ 0x où il peut empêcher la sémantique de déplacement de fonctionner.

Étant donné que les structs peuvent être assignées à et que votre q() retourne une copie de struct foo , elle affecte la structure renvoyée à la valeur fournie.

Cela ne fait pas vraiment quoi que ce soit dans ce cas-ci car la structure est hors de scope après coup et vous ne la conservez pas de toute façon (dans ce code spécifique).

Cela a plus de sens (même si ce n’est pas vraiment une “meilleure pratique”)

 struct foo { int a; }; foo* q() { foo *f = new malloc(sizeof(foo)); f->a = 4; return f; } int main() { foo i; ia = 5; //sets the contents of the newly created foo //to the contents of your i variable (*(q())) = i; } 

Une application intéressante de ceci:

 void f(const std::ssortingng& x); std::ssortingng g() { return ""; } ... f(g() += ""); 

Ici, g() += modifie le temporaire, ce qui peut être plus rapide que de créer un temporaire supplémentaire avec + car le tas alloué pour la valeur de retour de g () peut déjà avoir une capacité de réserve suffisante pour accueillir .

Regardez-le fonctionner sur ideone.com avec GCC / C ++ 11 .

Maintenant, quel novice en informatique a parlé des optimisations et du mal …? ; -].