2008-09-17 4 views

Répondre

16

1: La prise d'une adresse temporaire n'est pas autorisée. Visual C++ l'autorise en tant qu'extension de langue (les extensions de langue sont activées par défaut).

2: Ceci est parfaitement légal.

+1

il est interdit de prendre l'adresse d'un rvalue, pas un temporaire spécifiquement. c'est pourquoi c'est interdit; 'A()' renvoie un rvalue. –

+2

@underscore_d Vrai - J'ai utilisé le terme informel 'temporaire', plus précisément une variable temporaire sans nom, et, comme vous le dites à juste titre, une valeur rvalue. Si nous sommes pointilleux, 'A()' ne retourne pas un rvalue (les constructeurs n'ont pas de valeurs de retour), c'est une expression prvalue. –

+0

Bonne prise - il est trop facile de considérer réflexivement les constructeurs comme des appels de fonction. –

-2

parfaitement légal.

L'objet existera sur la pile pendant l'appel de la fonction, tout comme n'importe quelle autre variable locale.

0

Il avait l'air lke cela fonctionnerait, mais il ne se compilent pas avec g ++ avec l'option mur, voici ce que je reçois:

 
[email protected]:~/Desktop$ g++ -Wall a.cpp 
a.cpp: In function ‘int main()’:[email protected]:~/Desktop$ g++ -Wall a.cpp 
a.cpp: In function ‘int main()’: 
a.cpp:8: warning: taking address of temporary 
a.cpp:9: error: invalid initialization of non-const reference of type ‘A&’ from a temporary of type ‘A’ 
a.cpp:4: error: in passing argument 1 of ‘void bar(A&)’ 
[email protected]:~/Desktop$ 

On dirait que vous aurez besoin d'utiliser une référence constante.

+0

Mais le fait que MSVC et g ++ émettent tous les deux des avertissements pour (1) suggère qu'il pourrait ne pas être légal à 100%. Avez-vous une section de la norme ti cite C++? –

1

Ces objets A n'existeront que jusqu'à ce que l'exécution atteigne le point-virgule. Ainsi, les appels sont sûrs, mais n'essayez pas de sauvegarder le pointeur et de l'utiliser plus tard. En outre, le compilateur peut exiger que la barre prenne une référence const.

+0

'foo (& A()) peut être" sûr ", _if_ il compile. Ce n'est pas C++ valide. –

-1

C'est légal. Nous l'utilisons parfois pour fournir une valeur par défaut que nous pourrions vouloir ignorer.

int dosomething(error_code& _e = ignore_errorcode()) { 
    //do something 
} 

Dans le cas ci-dessus, il va construire un objet de code d'erreur vide si aucun error_code est passé à la fonction.

+0

Je suis sûr que votre ignore_errorcode() retourne un objet error_code avec plus de durée de vie qu'un objet créé par un constructeur par défaut ... – Pieter

-1

pour 2 // vous besoin d'une référence const

pour // 1 Je pense qu'il est légal, mais inutile

+0

Non, 'foo (& A())' est _not_ legal car 'A()' est une valeur, et vous ne pouvez pas prendre l'adresse d'une valeur. http://stackoverflow.com/a/2985578/2757035 –

9

Non, il est à la norme de passer une référence non-const à un objet temporaire. Vous pouvez utiliser une référence const:

class A{}; 

void bar(const A&); 

int main(void) 
{ 
    bar(A()); // 2 
} 

Ainsi, alors que certains observants acceptera, et il fonctionnerait aussi longtemps que ne pas utiliser la mémoire après la virgule, un compilateur conforme ne l'acceptera pas.

+4

Cette réponse est dépassée par une modification de l'OP –

5

foo n'est pas autorisé en C++ conforme standard, alors que bar est autorisé. Bien que les chances sont, foo compilera avec avertissement, et bar peut compiler ou non avec un avertissement.

A() créer un objet temporaire, à moins lié à une référence (comme cela est le cas dans bar), ou utilisée pour initialiser un objet nommé, est détruit à la fin de la pleine expression dans laquelle cela a été créé. Un temporaire créé pour contenir un initialiseur de référence persiste jusqu'à la fin de la portée de sa référence.Pour le cas de bar, c'est l'appel de fonction, de sorte que vous pouvez utiliser A à l'intérieur bar parfaitement en toute sécurité. Il est interdit de lier un objet temporaire (qui est un rvalue) à une référence non-const. Il est de même interdit de prendre l'adresse d'un rvalue (pour passer en argument pour initialiser A pour foo).

+0

Nécessite un refactoring pour clarifier les capacités d'amélioration de portée d'un referene sur une variable temporaire. –

+0

Ceci est la réponse supérieure, car il est juste que ce qui est interdit est de prendre l'adresse d'un rvalue - pas un temporaire spécifiquement. –

2

La réponse courte est oui.

Si l'objet est reçu par la fonction en tant que paramètre de référence const - comme vous l'avez modifié la méthode bar(const A&), alors c'est totalement légal. La fonction peut fonctionner sur l'objet, mais l'objet sera détruit après l'appel de la fonction (l'adresse de temporaire peut être prise, mais ne doit pas être stockée et utilisée après l'appel de fonction - voir la raison ci-dessous).

Le foo(A*) est également légal car l'objet temporaire est détruit à la fin de la fullexpression. Cependant la plupart du compilateur émettra un avertissement sur la prise d'adresse temporaire.

La version originale de bar(A&) ne doit pas compiler, il est contraire à la norme d'initialiser une référence non-const à partir d'un temporaire.

C++ chapitre norme 12,2

3 [...] objets temporaires sont détruits comme dernière étape dans l'évaluation de la fullexpression (1.9) que (lexicalement) contient le point où ils ont été créés. [...]

4 Il existe deux contextes dans lesquels les temporaires sont détruits à un point différent de la fin de la fullexpression. Le premier contexte est lorsqu'une expression apparaît comme un initialiseur pour un déclarateur définissant un objet. Dans ce contexte, le temporaire qui contient le résultat de l'expression doit persister jusqu'à ce que l'initialisation de l'objet soit terminée. [...]

5 Le deuxième contexte est celui où une référence est liée à un temporaire. Le temporaire auquel la référence est liée ou le temporaire qui est l'objet complet d'un sous-objet dont le temporaire est lié persiste pendant la durée de la référence, sauf indication contraire ci-dessous. Une liaison temporaire à un membre de référence dans le ctorinitializer d'un constructeur (12.6.2) persiste jusqu'à la sortie du constructeur. Une liaison temporaire à un paramètre de référence dans un appel de fonction (5.2.2) persiste jusqu'à la fin de l'expression complète contenant l'appel. Une liaison temporaire à la valeur renvoyée dans une déclaration de retour de fonction (6.6.3) persiste jusqu'à ce que la fonction se termine.

A fullexpression est une expression qui ne soit pas une sous-expression d'une autre expression.

+0

Non, 'foo (& A())' est _not_ legal car 'A()' est un rvalue, et vous ne pouvez pas prendre l'adresse d'un rvalue. http://stackoverflow.com/a/2985578/2757035 –

Questions connexes