Réponses:
C'est sûr. Const ref prolonge la durée de vie des temporaires. La portée sera la portée de la référence const.
La durée de vie d'un objet temporaire peut être étendue en se liant à une référence const lvalue ou à une référence rvalue (depuis C ++ 11), voir l' initialisation de la référence pour plus de détails.
Chaque fois qu'une référence est liée à un temporaire ou à un de ses sous-objets, la durée de vie du temporaire est étendue pour correspondre à la durée de vie de la référence, avec les exceptions suivantes :
- une liaison temporaire à une valeur de retour d'une fonction dans une instruction de retour n'est pas étendue: elle est détruite immédiatement à la fin de l'expression de retour. Une telle fonction renvoie toujours une référence pendante.
- un lien temporaire à un membre de référence dans une liste d'initialisation de constructeur persiste uniquement jusqu'à ce que le constructeur se termine, pas tant que l'objet existe. (note: une telle initialisation est mal formée à partir de DR 1696).
- une liaison temporaire à un paramètre de référence dans un appel de fonction existe jusqu'à la fin de l'expression complète contenant cet appel de fonction: si la fonction renvoie une référence, qui survit à l'expression complète, elle devient une référence pendante.
- une liaison temporaire à une référence dans l'initialiseur utilisé dans une nouvelle expression existe jusqu'à la fin de l'expression complète contenant cette nouvelle expression, pas aussi longtemps que l'objet initialisé. Si l'objet initialisé survit à l'expression complète, son membre de référence devient une référence pendante.
- une liaison temporaire à une référence dans un élément de référence d'un agrégat initialisé à l'aide de la syntaxe d'initialisation directe (parenthèses) par opposition à la syntaxe d'initialisation de liste (accolades) existe jusqu'à la fin de l'expression complète contenant l'initialiseur.
struct A { int&& r; }; A a1{7}; // OK, lifetime is extended A a2(7); // well-formed, but dangling reference
En général, la durée de vie d'un temporaire ne peut pas être prolongée davantage en la "transmettant": une deuxième référence, initialisée à partir de la référence à laquelle le temporaire était lié, n'affecte pas sa durée de vie.
comme @Konrad Rudolph l'a souligné (et voir le dernier paragraphe ci-dessus):
"Si
c.GetSomeVariable()
renvoie une référence à un objet local ou une référence indiquant qu'il prolonge lui-même la durée de vie d'un objet, l'extension à vie ne se déclenche pas"
c.GetSomeVariable()
renvoie une référence à un objet local ou une référence indiquant qu'il prolonge lui-même la durée de vie d'un objet, l'extension de durée de vie ne démarre pas .
Il ne devrait pas y avoir de problème ici, grâce à l' extension de la durée de vie . L'objet nouvellement construit survivra jusqu'à ce que la référence soit hors de portée.
Oui, cela est parfaitement sûr: la liaison à un const
référence étend la durée de vie du temporaire à la portée de cette référence.
Notez cependant que le comportement n'est pas transitif . Par exemple, avec
const auto& cc = []{
const auto& c = SomeClass{};
return c;
}();
cc
se balance.
C'est sûr.
[class.temporary]/5
: Il existe trois contextes dans lesquels les temporels sont détruits à un point différent de la fin de la pleine expression . [..]
[class.temporary]/6
: Le troisième contexte est lorsqu'une référence est liée à un objet temporaire. L'objet temporaire auquel la référence est liée ou l'objet temporaire qui est l'objet complet d'un sous-objet auquel la référence est liée persiste pendant toute la durée de vie de la référence si la valeur GL à laquelle la référence est liée a été obtenue par l'un des éléments suivants : [beaucoup de choses ici]
Il est sûr dans ce cas spécifique. Notez cependant que tous les temporaires ne sont pas sécurisés à capturer par référence const ... par exemple
#include <stdio.h>
struct Foo {
int member;
Foo() : member(0) {
printf("Constructor\n");
}
~Foo() {
printf("Destructor\n");
}
const Foo& method() const {
return *this;
}
};
int main() {
{
const Foo& x = Foo{}; // safe
printf("here!\n");
}
{
const int& y = Foo{}.member; // safe too (special rule for this)
printf("here (2)!\n");
}
{
const Foo& z = Foo{}.method(); // NOT safe
printf("here (3)!\n");
}
return 0;
}
La référence obtenue pour z
n'est PAS sûre à utiliser car l'instance temporaire sera détruite à la fin de l'expression complète, avant d'atteindre l' printf
instruction. La sortie est:
Constructor
here!
Destructor
Constructor
here (2)!
Destructor
Constructor
Destructor
here (3)!