63 votes

Où le pointeur 'this' est-il stocké dans la mémoire de l'ordinateur ?

Où se trouve exactement le pointeur 'this' en mémoire ? Est-il alloué sur la pile, dans le tas, ou dans le segment de données ?

#include <iostream>
using namespace std;

class ClassA
{
    int a, b;

    public:
        void add()
        {
            a = 10;
            b = 20;
            cout << a << b << endl;
        }
};

int main()
{
    ClassA obj;
    obj.add();
    return 0;
}

Dans le code ci-dessus, j'appelle la fonction membre add() et l'objet récepteur est transmis implicitement comme le pointeur 'this'. Où est this stockée en mémoire ?

78voto

unwind Points 181987

Le moyen le plus simple est de penser à this comme étant un argument supplémentaire caché qui est toujours passé automatiquement.

Donc, une méthode fictive comme :

size_t String::length(void) const
{
  return strlen(m_string);
}

est en fait plus comme ça sous le capot :

size_t String__length(const String *this)
{
  return strlen(this->m_string);
}

et un appel comme :

{
  String example("hello");
  cout << example.length();
}

devient quelque chose comme :

cout << String__length(&example);

Notez que la transformation ci-dessus est simplifiée, dans l'espoir de rendre mon point de vue un peu plus clair. Pas besoin de remplir les commentaires avec des objections du type "whaaa, où est le marshalling pour la surcharge des méthodes, hein ?)

Cela transforme la question en "où sont stockés les arguments ?", et la réponse est bien sûr "ça dépend" :)

Il est souvent sur la pile, mais il peut aussi être dans les registres, ou tout autre mécanisme que le compilateur considère comme bon pour l'architecture cible.

64voto

templatetypedef Points 129554

D'autres réponses ont fait un très bon travail en expliquant comment un compilateur typique implémente this (en le passant comme premier paramètre implicite de la fonction).

Je pense qu'il est également utile de voir ce que la spécification ISO C++ dit explicitement à ce sujet. Selon la spécification ISO C++03, §9.3.2/1 :

Dans le corps d'une fonction membre non statique (9.3), le mot-clé this est une expression sans valeur dont la valeur est l'adresse de l'objet pour lequel la fonction est appelée.

Il est important de noter que this es no une variable - c'est un expression de la même manière que l'expression 1 + 2 * 3 est une expression. La valeur de cette expression peut être stockée à peu près n'importe où. Le compilateur pourrait le mettre sur la pile et le passer comme un paramètre implicite à une fonction, ou il pourrait le mettre dans un registre, et il est concevable qu'il puisse le mettre dans le tas ou dans le segment de données. La spécification C++ donne délibérément à l'implémentation une certaine flexibilité ici.

Je pense que la réponse du "juriste du langage" est "ceci est complètement défini par l'implémentation, et de plus this n'est techniquement pas un pointeur, mais une expression qui évalue un pointeur".

J'espère que cela vous aidera !

34voto

Spook Points 11276

this est généralement passée en tant qu'argument caché de la méthode (la seule différence entre les différentes conventions d'appel est la suivante comment ).

Si vous appelez :

myClass.Method(1, 2, 3);

Le compilateur génère le code suivant :

Method(&myClass, 1, 2, 3);

Où le premier paramètre est en fait le pointeur vers this .

Vérifions le code suivant :

class MyClass
{
private:
    int a;

public:
    void __stdcall Method(int i)
    {
        a = i;
    }
};

int main(int argc, char *argv[]) 
{
    MyClass myClass;
    myClass.Method(5);

    return 0;
}

En utilisant __stdcall J'ai forcé le compilateur à passer tous les paramètres par la pile. Si vous lancez ensuite le débogueur et inspectez le code d'assemblage, vous trouverez quelque chose comme ce qui suit :

     myClass.Method(5);
00AA31BE  push        5  
00AA31C0  lea         eax,[myClass]  
00AA31C3  push        eax  
00AA31C4  call        MyClass::Method (0AA1447h)  

Comme vous le voyez, le paramètre de la méthode est passé par la pile, puis l'adresse de myClass est chargée dans le registre eax et à nouveau poussée sur la pile. En d'autres termes, this est traité comme un paramètre normal de cette méthode.

18voto

James Kanze Points 96599

this est une rvalue (vous ne pouvez pas prendre son adresse), donc il n'y a pas d'erreur. occupe pas (nécessairement) la mémoire du tout. Selon le compilateur et l'architecture cible, il sera souvent dans un registre : i0 sur un Sparc, ECX avec MSVC sur Intel, etc. Lorsque l'optimiseur est actif, il peut même se déplacer. (Je l'ai vu dans différents registres avec MSVC).

9voto

MvG Points 22342

this se comporte principalement comme un argument de fonction, et en tant que tel sera stocké sur la pile ou - si les conventions d'appel binaire de l'architecture le permettent - dans un registre.

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