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 …? ; -].