Je me demandais, pourquoi la voie de code suivante (déjà commentée) provoquera Y a-t-il un meilleur moyen d'éviter d'utiliser
C2102: '&' nécessite la valeur L CODE>
TMP code> variable? P>
class a {
private:
int *dummy;
public:
int* get_dummy() const {
return dummy;
}
};
int main()
{
a aa;
// error C2102: '&' requires l-value
//int** me = &(aa.get_dummy());
// OK!
int *tmp = aa.get_dummy();
int** me = &(tmp);
}
5 Réponses :
Non. P>
Quelle adresse Il n'y a pas de réponse significative à cette question, la norme nécessite donc que l'argument de me code> contient autrement? Ici, vous avez donné l'adresse de
TMP code> - mais si vous le remplacez par
int ** me = & aa.get_dummy (); code>, où serait-il pointant? P >
et code> soit un lvalue. P>
Où cela voudrait-il cela? Code> - N'est-il pas indiqué l'adresse de l'instance mannequin?
@YAN: Non. La fonction renvoie l'adresse (ou la valeur) stockée par mannequin code>, pas
mannequin code> lui-même.
@YAN: Vous pouvez retourner dummy par référence, par exemple int * & get_dummy.
Vous pouvez plutôt définir:
int **get_dummy() ... return &dummy;
HMM, vous pourrez peut-être utiliser & aa code>, mais sinon, pourquoi voulez-vous le pointeur indirect? N'y a-t-il pas d'API pour changer le pointeur? Voulez-vous même le changer? Il est dangereux de prendre l'adresse d'une variable locale ...
Soyez global, membre ou variable local, tant que sa vie dépasse le référent, le «danger» du pointeur pendling est inexistant.
@Yeenfei, bien sûr, mais le retour d'une adresse d'une locale est une opération exotique dans n'importe quelle langue. Lorsque les gens ne comprennent pas complètement la réalité de temps d'exécution, rester sur le côté plus sûrement est probablement une bonne idée.
L'opérateur & code> doit être appliqué à une lvalue. Lorsque l'appel
aa.get_dumy () code> n'est attribué à une variable, sa valeur de retour est uniquement mise sur la pile, de sorte qu'il serait idiot (et erroné) d'obtenir l'adresse d'un élément de pile. p>
parce que A :: get_dummy () code> renvoie un objet temporaire STRY> SNONOMED STORT> (Int Pointer). de
Objet renvoyé par fonction
Même problème que la réponse de Luca. TMP code> est un objet de pile!
Dummy code> n'est pas un objet temporaire ni un objet local.
@Naveen: Oui, c'est vrai. Mais la réponse ne dit pas "Sans nom Temporaire" (qui vit jusqu'à la fin de son expression complète), il est indiqué "objet de pile" qui signifie généralement un objet dans un stockage "automatique" qui vit jusqu'à la fin de sa portée.
@Billy, ajouté le "Sans nom" sur ma réponse. Mais je ne vois pas "l'objet de la pile" dans ma réponse que vous parlez de.
@Yeenfei: L'objet de pile est impliqué par "Haut du cadre de pile" et "hors de portée". TMP code> est également B> invalide quand il est hors de portée. Les temporaires de compilation sans nom ont absolument rien i> à faire avec la portée. Ils vivent jusqu'à la fin de leur propre expression.
@Naveen: Nous ne retournons pas Dummy (comme cela nécessiterait une référence). Nous retournons une copie de Dummy (un pointeur) en tant que telle, ce n'est pas une variable et nous ne pouvons donc pas prendre son adresse. Donc oui c'est une temporaire (pensez-y en tant que pointeur temporaire).
@Billy, d'accord, j'ai toujours référé "Durée de vie de l'expression" en tant que portée, suppose que ce n'était pas le mot d'autres utilisations.
@Yeenfei: la portée a une signification très spécifique selon la norme. Voir la section 3.3 pour une définition exhaustive (qui est de 2 pages). Dans ce cas, cependant, nous ne sommes concernés que par une portée de bloc (section 3.3.3), qui est "simplement" une demi-page long.
@Billy, édité une utilisation de "portée" dans ma réponse à "expression". Le "haut de la pile" reste vrai sauf si elle est attribuée à une référence (et de nouveaux temporaires peuvent être placés sur le dessus au lieu de celui-ci).
"Asseyez-vous sur le cadre de la pile" - pas nécessairement, ils pourraient être stockés dans des registres parfois.
Le compilateur a raison, selon ISO C ++ § 5.3.1.3 < / a>: Le résultat du fonctionnaire et de l'opérateur est un pointeur de son opérande. Les
L'opérande doit être un lvalue ou un identifiant qualifié. P>
blockQuote> En d'autres termes, vous pouvez prendre une adresse de tout ce que a un nom em>. p> valeurs renvoyées des fonctions On pourrait faire valoir que le compilateur pourrait être plus intelligent, détecter cela et stocker la valeur la pile pendant la durée de l'expression dans laquelle l'adresse est utilisée. Mais c'est-à-dire une erreur d'erreur (vous pouvez "étanguer" un pointeur à l'extérieur de l'expression) et serait clairement une extension em> de la norme (c'est-à-dire non garantie d'être compatible). Donc, MSVC l'interdit tout simplement. P> Divertir, le compilateur est em> que intelligent quand il s'agit de la référence em> à une rvalue. Mais il n'y a pas de telles fonctionnalités pour un pointeur em> à une rvalue. P> Pour répondre à votre question forte>: essayez de minimiser les adresses de choses; Prendre une adresse d'une variable empêche l'optimiseur de la mettre dans un registre.
Mais si vous devez, renvoyez une référence à la place: p> note que comportant un
const get_dumy () code> n'est pas strictement nécessaire, mais aidera le Optimiseur dans des contextes de rvalue. p> p>
renvoyer une référence au pointeur.
Dupliqué possible de Erreur "L-Value requise"