0
votes

Mécanisme de rendement de la fonction: Objet temporaire, Valeur R, Valeur L

Analyse de la question à son niveau bas, lorsqu'une fonction renvoie une valeur, elle est renvoyée dans un registre de la CPU ou dans un espace alloué sur la pile précédemment par l'appelant. À ce stade, la fonction d'appel peut prendre la valeur et la copier dans sa variable locale.

class1(10,20).i = 4;


1 commentaires

alors la fonction principale copie la valeur du registre EAX dans un emplacement de mémoire sur la pile. ou non, si le compilateur d'optimisation ne conserve que Risultato dans un registre comme EAX. Ou l'optimise complètement parce que dans ce cas, il est inutilisé. Dans Abstrait C, tous les objets ont une adresse mémoire (à l'exception de enregistrez INT FOO Variables), mais dans la pratique, à moins que vous ne désactivez que les variables d'optimisation ne disposent que d'adresses si le compilateur s'échappe des registres.


3 Réponses :


0
votes

Je sais que ce que je fais n'a aucune utilité dans la pratique

C'est la réponse à votre question:

Pourquoi dans ce cas est-il toujours interprété comme une valeur R et non comme une valeur L?

Il est plus difficile de mettre en œuvre le compilateur s'il doit en faire une valeur L et, étant donné qu'il n'a aucune utilité, cela ne vaut pas la peine.

Il y a des choses qui ne sont que pour la commodité des écrivains compilateurs.


0 commentaires

2
votes

Déménager maintenant à l'abstraction de C ++, si j'ai essayé de faire une opération comme celle-ci: somme (10,20) = 4; Cela me donne une erreur. En effet, la fonction ne renvoie pas l'emplacement de la mémoire dans lequel la valeur est contenue, mais la valeur elle-même. Par conséquent, une valeur R, cela ne sera pas assignable, car il n'est pas possible d'attribuer une valeur à une autre valeur. Le problème devient complètement différent lorsque l'opérateur de la derréférance * est utilisé. Dans ce cas, il ne sera pas renvoyé une valeur, mais l'emplacement de la mémoire elle-même (valeur L), qui sera donc assignable.

Ce que j'ai écrit correct?

genre de. Vous dites

Ceci est dû au fait que la fonction ne renvoie pas l'emplacement de la mémoire dans lequel la valeur est contenue

Mais ce n'est pas ce qui se passe. Un objet est retourné, cet objet a une valeur. Ce qui en fait un rvalue est que la fonction "retourne par valeur" (un autre nom pour créer un objet temporaire).

Par conséquent, une valeur R, cela ne sera pas assignable, car il n'est pas possible d'attribuer une valeur à une autre valeur

Ceci est seulement vrai pour les types intégrés. L'opérateur d'affectation de types intégrés nécessite que l'objet soit attribué à une lvalue. Si vous avez un type défini par l'utilisateur ( classe , struct ), vous pouvez attribuer à une rvalue.

Dans ce cas, je crée un objet temporaire, je ne comprends pas pourquoi cela ne me donne pas la possibilité d'attribuer la variable de l'objet I, pourquoi dans ce cas est-il toujours interprété comme une valeur R et non une valeur L?

La raison est qu'avec opérateur. Si l'objet que vous appelez est un rvalue, le membre que vous accédez est traité comme une r devalue. Puisque i est un type intégré et une rvalue, vous ne pouvez pas l'affecter.


16 commentaires

Je veux dire qu'au point du code où j'appelle la fonction, c'est comme si j'avais une valeur et non un emplacement de mémoire, lorsqu'une valeur R est renvoyée. Est-ce que cela se passe mal?


@ Tony92 La machine abstraite C ++ ne fait pas ce genre de distinction. Vous avez renvoyé un objet par valeur (créé un objet temporaire) et tous les objets temporaires sont des avales.


Okok merci beaucoup. Ainsi, lorsque je tapez le nom d'une fonction suivie des crochets ronds, je dois penser à ce point comme objet temporaire. Est-ce que la même chose se produit même lorsque j'utilise l'opérateur d'adresses et? Dans ce cas, un pointeur (adresse) est renvoyé et est-ce toujours une valeur R?


@ Tony92 Si vous revenez par référence, vous n'avez plus de rvalue. Avoir int global = 42; int & foo () {retour global; } FOO () = 21; est légal car les références sont toujours considérées comme des lvalues. Il semble vraiment que vous puissiez utiliser un Good C ++ Book . C ++ est une langue très complexe et un livre approprié est l'un des meilleurs moyens de l'apprendre.


Oui, si je renvoie une référence, qui est un pointeur automatiquement déréférencé, je reçois une valeur L. Mais si la fonction renvoie un pointeur, une valeur R est renvoyée et non une valeur L. tout à fait vrai?


@ Tony92 Oui, si vous renvoyez un pointeur par valeur, vous retournez temporaire. Accéder à ce pointeur à l'aide de * , cependant vous donnerait un lvalue comme Opérateur * renvoie une référence et une référence est toujours un lvalue. int global = 42; int * foo () {retour & global; } * foo () = 21; serait un code juridique.


Cela montre comment un pointeur peut être à la fois une valeur R et une valeur L. int i = 10; int * ptr = & I; & I -> R-Valeur PTR -> L-Valeur. Je pouvais utiliser les deux, seulement que le premier n'est pas assignable?


@ Tony92 Yep. Vous ne pouvez pas faire & i = pTR; , mais vous pouvez faire * & i = 42;


peut donc être considéré et je un objet temporaire? Le concept de pointeur peut-il également être étendu à l'adresse seulement et non seulement à la variable contenant l'adresse elle-même?


@ Tony92 & i retourne un objet temporaire. Un pointeur contient juste l'adresse d'un objet. Vous devez indirect à travers le pointeur pour obtenir l'objet que le pointeur pointe.


Est-il possible d'avoir une adresse qui est stockée nulle part?


@ Tony92 Je ne suis pas sûr exactement ce que vous demandez, mais je vais dire que la réponse est non. Quel serait le but d'une adresse qui est stockée nulle part? Comment allez-vous accéder une telle chose?


Pourquoi amusant () = classe1 (4,5) est compilé? amusant (). i = 5 donne une erreur, tout en amusant () = classe1 (4,5) non


@ Tony92 Comme je l'ai dit dans ma réponse, vous devez avoir une lvalue pour des types intégrés ( int , double , char ). Étant donné que classe1 n'est pas un type intégré, vous êtes autorisé à attribuer à des objets de rvalue.


restant dans le contexte de l'objet temporaire. int arr [3] = {10,20,30}; ; est dans ce cas créer un objet temporaire pour le nouveau pointeur calculé * (arr + 1) = 4?


@ Tony92 Conceptuellement (ARR + 1) fera une temporaire mais le compilateur optimisera probablement cela.



0
votes

@nathanoliver a répondu à la partie de la machine abstraite C ++. Je vais simplement ajouter une note sur la manière dont cette carte vers ASM.

Ensuite, la fonction principale copie la valeur du registre EAX dans un emplacement de mémoire sur la pile.

ou non, si le compilateur d'optimisation ne conserve que Risultato dans un registre comme EAX. Ou l'optimise complètement parce que dans ce cas, il est inutilisé.

dans Abstrait C Chaque objet a une adresse de mémoire (à l'exception de enregistrez INT FOO variables), mais dans la pratique, à moins que vous ne désactivez que les variables d'optimisation ne disposent que d'adresses si le compilateur s'étend sur des registres.

L'objet de retour de valeur est dans EAX.

Notez que les conventions d'appel traditionnels C ++ ne renvoient jamais des objets de manière triviale aux registres. Un constructeur ou un destructeur non trivial obligera même une structure d'un membre à retourner par un pointeur caché, afin de vous assurer que le constructeur et le destructeur ont un cohérent ce . (Les règles de la convention appelante ne peuvent pas dépendre du contenu des fonctions constructrice et destructeurs, il est simplement de définir le tout.)


0 commentaires