Question

Est-il possible de changer l'objet temporaire et de le passer en argument ?

struct Foo {    
   Foo& ref() { return *this; }
   Foo& operator--() { /*do something*/; return *this; }
   // another members
};
Foo getfoo() { return Foo(); } // return Foo() for example or something else
void func_val(Foo x) {}
void func_ref(const Foo & x) {}

int main() {
   func_val(--getfoo());     // #1 OK?
   func_ref(getfoo());       // #2 OK?
   func_ref(getfoo().ref()); // #3 OK?
   // the following line is a real example 
   //    using --vector.end() instead of --getfoo()
   func_ref(--getfoo());     // #4 OK? 

   const Foo & xref = --getfoo(); //  Does const extend the lifetime ?
   func_ref(xref);     // #5 OK? 
   func_val(xref);     // #6 OK? 

}

On sait que l'attribution d'un objet temporaire à la référence const prolonge la durée de vie de cet objet temporaire.Et qu’en est-il des lignes n°4 et n°5 de mon code ?Est-il vrai que la référence x est toujours valide dans la fonction func_ref ?Le fait est que l'opérateur renvoie une référence et le compilateur ne voit aucune relation entre cette référence et le temporaire que nous avons créé.

Était-ce utile?

La solution

func_val(--getfoo());     // #1 OK?

Oui ok.Le operator-- est une fonction membre, qui est appelée et qui se renvoie elle-même (et lvalue se référant à elle-même).L'objet est ensuite copié dans le paramètre de func_val.Notez que l'optimisation de la valeur de retour n'est pas autorisée, car le temporaire créé par getfoo() était auparavant lié à une référence.

func_ref(getfoo());       // #2 OK?

Oui ok.L'appel getfoo() renvoie un temporaire qui est lié à la référence const.Un constructeur de copie est requis, mais son appel peut être optimisé par l'implémentation.Le temporaire persiste jusqu'à la fin de l'expression complète contenant l'appel à func_ref (l'intégralité de la déclaration d'expression ici).

func_ref(getfoo().ref());

Oui ok.Aucun constructeur de copie n'est requis, car nous lions la référence const non pas à un temporaire mais à la lvalue représentant l'objet lui-même.

// the following line is a real example 
//    using --vector.end() instead of --getfoo()

Ce n’est pas nécessaire pour fonctionner.Pensez à une situation où vector.end() renvoie un T* (autorisé).Vous n'êtes pas autorisé à modifier des rvalues ​​de type non-classe, donc dans ce cas, cela serait mal formé.

func_ref(--getfoo()); 

Oui ok.L'argument est évalué comme dans #1, mais la lvalue résultante est directement transmise et la référence const y est liée.En ce sens, c'est égal à #3 (sauf pour l'effet secondaire de décrémentation).

const Foo & xref = --getfoo();

Le libellé de la norme n'est pas tout à fait clair.Il vise sûrement uniquement à prolonger la durée de vie des objets non encore liés à une référence.Mais dans notre cas, --getfoo() renvoie une lvalue faisant référence à un objet temporaire qui était auparavant lié à une référence.Cela vaut peut-être la peine de soumettre un rapport de défaut au comité (j'ai peut-être également manqué un libellé exigeant que l'objet temporaire ne soit pas encore lié à une référence).

Dans tous les cas, le comportement recherché est de détruire le temporaire résultant de getfoo() à la fin de l'initialisation xref, donc xref deviendra une référence pendante.

Le fait est que l'opérateur renvoie une référence et le compilateur ne voit aucune relation entre cette référence et le temporaire que nous avons créé.

Exactement (mais s'applique uniquement à l'initialisation de xref qui deviendra fou.Dans tous les autres cas, le comportement souhaité (ou ce que je pense que vous souhaitez) est atteint).

Autres conseils

Temporaries vivent toujours pendant toute la durée de la pleine expression dans laquelle ils sont créés de toute façon. Par conséquent, dans le Déclaration d'expression func_val(--getfoo());, la durée de vie du temporaire retourné par l'expression getfoo() n'a pas besoin de l'extension. La déclaration ne se termine qu'après func_val() était de retour.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top