considérez quelque chose comme ceci:
#include <iostream>
struct C {
C(double x=0, double y=0): x(x) , y(y) {
std::cout << "C ctor " << x << " " <<y << " " << "\n";
}
double x, y;
};
struct B {
B(double x=0, double y=0): x(x), y(y) {}
double x, y;
};
struct A {
B b[12];
A() {
b[2] = B(2.5, 14);
b[4] = B(56.32,11.99);
}
};
int main() {
const B& b = A().b[4];
C c(b.x, b.y);
}
quand je compile avec -O0 je reçois l'impression
C ctor 56.32 11.99
mais quand je compile avec -O2 je reçois
C ctor 0 0
Je sais que nous pouvons utiliser la référence const pour prolonger un temporaire local, donc quelque chose comme
const A& a = A();
const B& b = a.b;
serait parfaitement légal. mais j'ai du mal à trouver la raison pour laquelle le même mécanisme/règle ne s'applique pas à tout type de temporaire
MODIFIER POUR RÉFÉRENCE FUTURE:
J'utilise la version 6.3.0 de gcc
Votre code doit être bien formé, car pour temporaires
(c'est moi qui souligne)
Chaque fois qu'une référence est liée à un temporaire ou à un sous-objet de celui-ci, la durée de vie du temporaire est étendue pour correspondre à la durée de vie de la référence
Étant donné A().b[4]
, b[4]
Est le sous-objet de b
et le membre de données b
est le sous-objet du temproray A()
, dont la durée de vie devrait être prolongée.
EN DIRECT sur clang10 avec -O2
EN DIRECT sur gcc10 avec -O2
BTW: Cela semble être un bug de gcc qui a été corrigé.
De la norme, [class.temporary]/6
Le troisième contexte est lorsqu'une référence est liée à un objet temporaire.6 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 :
...
[ Exemple:
template<typename T> using id = T; int i = 1; int&& a = id<int[3]>{1, 2, 3}[i]; // temporary array has same lifetime as a const int& b = static_cast<const int&>(0); // temporary int has same lifetime as b int&& c = cond ? id<int[3]>{1, 2, 3}[i] : static_cast<int&&>(0); // exactly one of the two temporaries is lifetime-extended
- exemple de fin]
A (). B [4] n'est pas un temp ou une rvalue, c'est pourquoi cela ne fonctionne pas. Alors que A() est temporaire, vous créez une référence à un élément de tableau qui existe au moment de la création. Le dtor déclenche alors pour A (), ce qui signifie l'accès ultérieur à bb devient un comportement quelque peu indéfini. Vous devez conserver le A & pour vous assurer que le b reste valide.
const A& a = A();
const B& b = a.b[4];
C c(b.x, b.y);