37 votes

C++ - utiliser une référence constante pour prolonger un membre d'un temporaire, ok ou UB?

Pensez à quelque chose comme ça:

#include 

struct C {
    C(double x=0, double y=0): x(x) , y(y) {
        std::cout << "C ctor " << x << " " <

`

quand je compile avec -O0, j'obtiens l'impression

C ctor 56.32 11.99

mais quand je compile avec -O2, j'obtiens

 C ctor 0 0

Je sais que nous pouvons utiliser une référence constante pour prolonger une variable temporaire locale, 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 à n'importe quel type de variable temporaire

MODIFICATION POUR RÉFÉRENCE FUTURE:

Je utilise gcc version 6.3.0

`

34voto

songyuanyao Points 2265

Votre code doit être bien formé, car pour les temporaires

(soulignement de moi)

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 temporaire A(), dont la durée de vie devrait être prolongée.

EN DIRECT sur clang10 avec -O2
EN DIRECT sur gcc10 avec -O2

BTW: Il semble qu'il s'agisse d'un bug de gcc qui a été corrigé.

D'après la norme, [class.temporary]/6

Le troisième contexte est lorsque une référence est liée à un objet temporaire.36 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 pour la durée de vie de la référence si le glvalue auquel la référence est liée a été obtenu par l'une des actions suivantes :

...

[ Exemple :

template using id = T;

int i = 1;
int&& a = id{1, 2, 3}[i];          // l'array temporaire a la même durée de vie que a
const int& b = static_cast(0); // l'entier temporaire a la même durée de vie que b
int&& c = cond ? id{1, 2, 3}[i] : static_cast(0);
                                           // exactement l'un des deux temporaires est prolongé dans le temps

— fin de l'exemple ]

0voto

robthebloke Points 1301

A().b[4] n'est pas une temporaire ou une rvalue, c'est pourquoi ça ne fonctionne pas. Alors que A() est un temporaire, vous créez une référence à un élément de tableau qui existe au moment de sa création. Le destructeur est ensuite déclenché pour A(), ce qui signifie que l'accès ultérieur à b.b devient quelque peu un comportement indéfini. Vous auriez besoin de conserver la référence A& pour vous assurer que b reste valide.

    const A& a = A();
    const B& b = a.b[4];
    C c(b.x, b.y);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X