L'appel de élision d'une "optimisation" est une idée fausse. Les compilateurs sont autorisés à ne pas le faire, mais ils sont également autorisés à mettre en oeuvre a+b
entier plus comme une séquence d'opérations bit à bit avec manuel transporter.
Un compilateur qui ne qui serait hostile: le compilateur qui refuse de les éluder.
Élision n'est pas comme les "autres" optimisations, comme ceux qui s'appuient sur le cas de la règle (comportement peut changer tant qu'il se comporte comme si la norme dicte). Élision peut modifier le comportement du code.
Pourquoi l'aide d' const &
ou même rvalue &&
est une mauvaise idée, les références sont des alias à un objet. Avec soit, vous n'avez pas (local) de garantir que l'objet ne soit pas manipulée par ailleurs. En fait, si la fonction renvoie un &
, const&
ou &&
, l'objet doit exister ailleurs, avec une autre identité dans la pratique. Donc votre "local" valeur est plutôt une référence à un inconnu lointain de l'état: ce qui rend le comportement difficile à comprendre.
Valeurs, d'autre part, ne peut pas être un alias. Vous pouvez former ces alias après la création, mais un const
valeur locale ne peut pas être modifié en vertu de la norme, même s'il existe un alias pour elle.
Raisonner sur les objets locaux est facile. Raisonner sur les objets distribués est dur. Les références sont distribués de type: si vous devez choisir entre un cas de référence ou de la valeur et il n'est pas évident de performance coût de la valeur, toujours choisir des valeurs.
Pour être concret:
Foo const& f = GetFoo();
pourrait être une référence de la liaison à un temporaire de type Foo
ou dérivé retourné à partir de GetFoo()
, ou une référence lié à quelque chose d'autre stockés dans GetFoo()
. Nous ne pouvons pas dire à partir de cette ligne.
Foo const& GetFoo();
vs
Foo GetFoo();
faire f
ont des significations différentes, en effet.
Foo f = GetFoo();
toujours créer une copie. Rien qui ne modifie pas "par" f
modifiera f
(à moins que son ctor passé un pointeur sur lui-même pour quelqu'un d'autre, bien sûr).
Si nous avons
const Foo f = GetFoo();
nous avons même la garantie que la modification de la (non-mutable
pièces d') f
est un comportement indéfini. On peut supposer f
est immuable, et, en fait, le compilateur va le faire.
Dans l' const Foo&
des cas, la modification d' f
peut être défini comportement si le stockage sous-jacent est non-const
. Donc nous ne pouvons pas assumer f
est immuable, et le compilateur ne supposons qu'il est immuable, si l'on peut examiner l'ensemble du code qui a valablement dérivé des pointeurs ou des références à d' f
et de déterminer qu'aucun d'entre eux muter (même si vous venez de passer autour de const Foo&
, si l'objet d'origine était un non-const
Foo, il est légal d' const_cast<Foo&>
et de la modifier).
En bref, ne pas prématuré pessimize et d'assumer élision "ne marchera pas." Il y a très peu de courant compilateurs ne pas éluder sans explicitement de l'éteindre, et vous avez presque certainement ne serez pas en la construction d'un projet sérieux sur eux.