web-dev-qa-db-fra.com

Pointeur C++ vers les objets

En C++, avez-vous toujours initialisé un pointeur sur un objet avec le mot clé new?

Ou pouvez-vous simplement avoir ceci aussi:

MyClass *myclass;

myclass->DoSomething();

Je pensais que c'était un pointeur alloué sur la pile au lieu du tas, mais comme les objets sont normalement alloués au tas, je pense que ma théorie est probablement erronée?

S'il vous plaît des conseils.

21
Tony The Lion

Non, vous pouvez avoir des pointeurs pour empiler les objets alloués:

MyClass *myclass;
MyClass c;
myclass = & c;
myclass->DoSomething();

Ceci est bien sûr courant lorsque vous utilisez des pointeurs comme paramètres de fonction:

void f( MyClass * p ) {
    p->DoSomething();
}

int main() {
    MyClass c;
    f( & c );
}

D'une manière ou d'une autre, le pointeur doit toujours être initialisé. Votre code:

MyClass *myclass;
myclass->DoSomething();

conduit à cette condition redoutée, comportement non défini .

33
anon

Non, vous ne pouvez pas faire cela, MyClass *myclass définira un pointeur (la mémoire du pointeur étant allouée sur la pile) pointant vers un emplacement de mémoire aléatoire. Essayer d'utiliser ce pointeur provoquera un comportement indéfini.

En C++, vous pouvez créer des objets sur pile ou tas comme ceci:

MyClass myClass;
myClass.DoSomething();

Ci-dessus va allouer myClass sur pile (le terme n’est pas dans la norme, mais j’utilise pour plus de clarté). La mémoire allouée pour l'objet est automatiquement libérée lorsque la variable myClass sort de la portée.

Une autre façon d’allouer de la mémoire est de faire une new. Dans ce cas, vous devez prendre soin de libérer la mémoire en effectuant vous-même delete.

MyClass* p = new MyClass();
p->DoSomething();
delete p;

Rappelez-vous la partie delete, sinon il y aura une fuite de mémoire. 

Je préfère toujours utiliser les objets alloués à la pile autant que possible car je n'ai pas à me soucier de la gestion de la mémoire.

22
Naveen

si vous voulez que l'objet soit sur la pile, essayez ceci:

MyClass myclass;
myclass.DoSomething();

Si vous avez besoin d'un pointeur sur cet objet:

MyClass* myclassptr = &myclass;
myclassptr->DoSomething();
10
Johan Kotlinski

D'abord, je dois dire que votre code, 

MyClass *myclass;
myclass->DoSomething();

provoquera un comportement non défini . Le pointeur "myclass" ne pointant sur aucun objet de type "MyClass".

Ici, j'ai trois suggestions pour vous: - 

option 1: - Vous pouvez simplement déclarer et utiliser un objet de type MyClass sur la pile, comme indiqué ci-dessous.

MyClass myclass; //allocates memory for the object "myclass", on the stack.
myclass.DoSomething();

option 2: - En utilisant l'opérateur new.

MyClass *myclass = new MyClass();

Trois choses vont se passer ici.

i) Alloue de la mémoire pour l'objet de type "MyClass" sur le tas.

ii) Alloue de la mémoire pour le pointeur de type "MyClass" "myclass" sur la pile. 

iii) le pointeur "myclass" pointe vers l'adresse mémoire de l'objet de type "MyClass" sur le tas

Maintenant, vous pouvez utiliser le pointeur pour accéder à FONCTIONS MEMBRES de l'objet après avoir déréférencé le pointeur par "->"

myclass->DoSomething();

Mais vous devez libérer la mémoire allouée à l'objet de type "MyClass" sur le tas, avant de quitter l'étendue, à moins que vous ne souhaitiez qu'elle existe. Sinon, cela entraînera un fuite de mémoire !

delete myclass; // free the memory pointed by the pointer "myclass"

option 3: - vous pouvez aussi faire comme ci-dessous.

MyClass myclass; // allocates memory for the "MyClass" type object on the stack.
MyClass *myclassPtr; // allocates memory for the "MyClass" type pointer on the stack.
myclassPtr = &myclass; // "myclassPtr" pointer points to the momory address of myclass object.

Désormais, le pointeur et l'objet se trouvent tous les deux sur la pile . Vous ne pouvez maintenant pas renvoyer ce pointeur à l'extérieur de l'étendue actuelle, car la mémoire allouée du pointeur et l'objet seront libérés tout en sortant de l'étendue.

En résumé, les options 1 et 3 alloueront un objet sur la pile, tandis que seule l'option 2 le fera sur le tas.

2
Malith

si vous voulez accéder à une méthode:

1) en utilisant un objet d'une classe:

Myclass myclass;
myclass.DoSomething();

2) en utilisant un pointeur sur un objet d'une classe:

Myclass *myclass=&abc;
myclass->DoSomething();
1
harsha217

Si vous avez défini une méthode dans votre classe comme statique, cela est en fait possible.

    class myClass
    {
    public:
        static void saySomething()
        {
            std::cout << "This is a static method!" << std::endl;
        }
    }; 

Et de main, vous déclarez un pointeur et essayez d’appeler la méthode statique.

    myClass * pmyClass;
    pmyClass->saySomething();

/*    
Output:
This is a static method!
*/

Cela fonctionne correctement car les méthodes statiques n'appartiennent pas à une instance spécifique de la classe et ne sont pas allouées en tant que partie d'une instance de la classe. 

En savoir plus sur les méthodes statiques ici: http://fr.wikipedia.org/wiki/Static_method#Static_methods

1
Parth Kothari

Solution simple pour le pointeur de conversion sur l'objet

Démo en ligne

class myClass
{
  public:
  void sayHello () {
    cout << "Hello";
  }
};

int main ()
{
  myClass* myPointer;
  myClass myObject = myClass(* myPointer); // Cast pointer to object
  myObject.sayHello();

  return 0;
}
0
Ali Soltani