2010-06-07 23 views
15

En C++, ¿siempre ha inicializado un puntero a un objeto con la palabra clave new?Puntero C++ a los objetos

O puede simplemente tener esto también:

MyClass *myclass; 

myclass->DoSomething(); 

pensé que esto era un puntero asignado en la pila en lugar del montón, pero ya que los objetos son normalmente asignados montón, creo que mi teoría es probablemente defectuoso? ?

Por favor consejo.

+1

Los objetos no son normalmente montón asignado. Solo los objetos asignados dinámicamente (es decir, los asignados con la palabra clave 'new') están en el montón. Las variables locales, así como los punteros (no los objetos a los que apuntan) se encuentran en la pila. –

Respuesta

26

No, usted puede tener punteros para apilar objetos asignados:

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

Esto es, por supuesto, común al usar punteros como parámetros de la función:

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

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

De una forma u otra, el puntero siempre debe inicializarse. Su código:

MyClass *myclass; 
myclass->DoSomething(); 

conduce a esa condición temida, comportamiento indefinido.

+0

Buena respuesta, aunque la línea 3 no debería leer 'myclass = ...'? Como está ahora, está desmarcando un puntero no válido y dándole la dirección de c, ¿o estoy en extrema necesidad de cafeína? – Skurmedel

+1

@Skurmedel Por supuesto que debería, gracias. –

19

No, no puede hacer eso, MyClass *myclass definirá un puntero (memoria para el puntero se asigna en la pila) que apunta a una ubicación de memoria aleatoria. Intentar utilizar este puntero provocará un comportamiento indefinido.

En C++, puede crear objetos, ya sea en la pila o montón así:

MyClass myClass; 
myClass.DoSomething(); 

encima asignará myClass en la pila (el término no está allí en la norma, pero creo que estoy usando para mayor claridad) . La memoria asignada para el objeto se libera automáticamente cuando la variable myClass queda fuera del alcance.

Otra forma de asignar memoria es hacer un new. En ese caso, debes encargarte de liberar la memoria haciendo tú mismo delete.

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

Recuerde que la parte delete, de lo contrario no habrá pérdida de memoria.

Siempre prefiero usar la pila de objetos asignados siempre que sea posible, ya que no tengo que preocuparme por la gestión de la memoria.

9

si desea que el objeto en la pila, intente esto:

MyClass myclass; 
myclass.DoSomething(); 

Si necesita un puntero a ese objeto:

MyClass* myclassptr = &myclass; 
myclassptr->DoSomething(); 
1

si desea acceder a un método:

1) durante el uso de un objeto de una clase:

Myclass myclass; 
myclass.DoSomething(); 

2) durante el uso de un puntero a un objeto de una clase:

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

Si ha definido un método dentro de su clase como estático, esto es realmente posible.

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

Y desde main, declara un puntero e intenta invocar el método estático.

myClass * pmyClass; 
    pmyClass->saySomething(); 

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

Esto funciona bien porque los métodos estáticos no pertenecen a una instancia específica de la clase y no se asignan como parte de cualquier instancia de la clase.

Leer más en métodos estáticos aquí: http://en.wikipedia.org/wiki/Static_method#Static_methods

2

En primer lugar tengo que decir que su código,

MyClass *myclass; 
myclass->DoSomething(); 

provocará un undefined behavior. Porque el puntero "myclass" no apunta a ningún objeto de tipo "Mi Clase".

aquí tengo tres sugerencias para usted: -

la opción 1: - Simplemente puede declarar y utilizar un objeto de tipo MiClase en la pila de la siguiente manera.

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

opción 2: - Al utilizar el nuevo operador.

MyClass *myclass = new MyClass(); 

Tres cosas se van a encontrar aquí.

i) Asigna la memoria para el objeto tipo "MyClass" en el montón.

ii) Asigna la memoria para el puntero de tipo "MyClass" "myclass" en la pila.

iii) Puntero "miclase" apunta a la dirección de memoria del objeto de tipo "MyClass" en el montón

Ahora se puede utilizar el puntero para acceder a member functions del objeto después de la eliminación de referencias al puntero "-> "

myclass->DoSomething(); 

Pero debe liberar la memoria asignada a 'MiClase objeto' tipo en el montón, antes de regresar del ámbito de aplicación a menos que quiera que exista. De lo contrario, provocará un memory leak!

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

opción 3: - también se puede hacer de la siguiente manera.

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. 

Ahora, tanto el puntero como el objeto están en la pila. Ahora no puede devolver este puntero al exterior del alcance actual porque ambas memorias asignadas del puntero y el objeto se liberarán al salirse del alcance.

Como resumen, las opciones 1 y 3 asignan un objeto a la pila, mientras que solo la opción 2 lo hará en el montón.

+1

opción 3: - ¿está en montón o pila? Por favor, lea su última línea nuevamente. – UnKnown

+0

gracias @AsifMushtaq por señalar el error. – Malith

0

solución simple para el indicador del elenco de oponerse

Online demo

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

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

    return 0; 
}