2011-11-23 25 views
16

Si tengo una clase RectangleInicializar un objeto con y sin nuevo operador

class Rectangle{ 

private: 
    double width; 
    double height; 


public: 
void Set(double w , double l){ 
    width = w; 
    height = l; 
} 
}; 

y yo decleare tal objeto:

Rectangle *Obj; 

y luego tratar de inicializar sus propiedades:

Obj->Set(3,5); 

el compilador muestra en tiempo de ejecución: The variable 'Obj' is being used without being initialized.

El problema puede ser resuelto por:

Rectangle *Obj=new Rectangle; 

Me gustaría preguntar acerca de la razón! ¿Y por qué el compilador no muestra ningún error en el tiempo de compilación?

Respuesta

20
Rectangle *Obj; 

simplemente define un punteroa un objeto de clase Rectangle. La definición de un puntero no reserva ninguna memoria para el objeto en sí, solo para el puntero. Por lo tanto, si accede al puntero, es probable que termine en una dirección en la memoria que ni siquiera pertenece a su proceso. Sin embargo, el compilador no puede saber que no ha inicializado el puntero (la palabra clave aquí es aliasing) y, por lo tanto, no puede generar un mensaje de error.

La solución es o bien utilizando new como usted sugiere, o declarar una instancia de Rectangle así:

Rectangle Obj; 

que llamar a un constructor por defecto. A continuación, puede configurar sus miembros utilizando

Obj.Set(3, 5); 
+7

Solo un comentario, pero 'Rectangle * Obj;' no solo _declare_; también _define_. Y reserva memoria; suficiente memoria para almacenar un puntero. –

+0

@JamesKanze: Por supuesto, tienes razón. Actualizaré mi respuesta de inmediato – arne

7

y yo decleare tal objeto:

Rectangle *Obj; 

incorrecto, esto declara un puntero , no un objeto. Los punteros deben inicializarse utilizando new o asignándoles la dirección de un objeto existente.

+3

un puntero es un objeto, al menos en C++. Esto define un objeto con el tipo 'Rectangle *'. Sin inicializar, por supuesto. –

4

Mmm un poco de confusión existe:

el compilador muestra en tiempo de ejecución: La variable 'obj' está siendo utilizado sin ser inicializado

Eso es lo que se llama tiempo de compilación. Simplemente enderezando la jerga.

Además, la forma más sencilla sería la de

Rectangle Obj; 
Obj.Set(3,5); 

que es suficiente para la mayoría de los casos, a excepción de las asignaciones dinámicas o contenedores polimórficos:

std::vector<Shape*> v; 
v.push_back(new Rectange()); 
v.back()->Set(3,5); 

v.push_back(new Circle()); 
v.back()->Set(3,5); 

// 

Aunque siempre que use new usted debe estar recordando al delete también. Esto puede ser una verdadera pesadilla (a la luz de las excepciones, también). Sugiero:

std::vector<std::shared_ptr<Shape*> > v; 
v.push_back(std::make_shared<Rectange>()); 
v.back()->Set(3,5); 

v.push_back(std::make_shared<Circle>()); 
v.back()->Set(3,5); 
+2

¿No sería la forma más simple (y mejor) de ser: 'Rectangle Obj = {3, 5};'. Como regla general, no debe crear objetos no inicializados. (Sobre la única excepción podría ser si está leyendo en ella, usando '>>', en la siguiente declaración.) –

+1

@JamesKanze: 'Rectangle Obj' no crea un objeto no inicializado (al menos no asumo) es una estructura sin un constructor por defecto Y sin inicializadores de campo. Además, tiendo a no arrojar detalles de C++ 11 en las respuestas de principiante; shared_ptr se puede usar desde el impulso, la inicialización uniforme no puede. (** PS ** 'width y 'height' son privadas de todos modos) – sehe

+2

Hace con su implementación de' Rectangle'. Y me perdí el 'private'; no hay forma de crear un' Rectangle' inicializado. Necesita un constructor, no un 'Set' función. –

2

por qué el compilador no muestra ningún error en tiempo de compilación?

Porque, es sintacticamente correcto. Sin embargo, tales declaraciones darán lugar a comportamiento indefinido, los compiladores inteligentes siempre emitirán advertencias.

En g ++ puede activar este tipo de advertencia del compilador en los errores.

3

Con Rectangle *Obj;, está declarando un puntero a un rectángulo, pero no le ha dicho a Obj a qué rectángulo debe apuntar. Puede establecer o crear una instancia de Obj más adelante en un Rectangle existente o solo si lo necesita.

C++ se trata de darle un control preciso sobre la memoria y el rendimiento. De hecho, ¡es por eso que se usa en algunos entornos integrados! instanciar automáticamente Obj plantea varios "problemas"

  • ¿Cuándo nos liberamos Obj?
  • ¿Quién libera Obj?
  • ¿Qué ocurre con las implicaciones de rendimiento de crear un Rectangle en el montón?
  • ¿Es este un entorno en el que tenemos suficientes recursos (memoria, CPU, etc.) para incluso crear el rectángulo, especialmente si es grande.
  • ¿Pasa la dirección de Obj a algún lugar y luego lo instancia en tiempo de ejecución a través de algún método complejo que no podemos analizar estáticamente?

Lo que hace no es un error de sintaxis, que es en lo que los compiladores arrojan errores - errores al compilar. Un analizador (uno está integrado en Visual Studio 2010 Professional) podría advertirle que está utilizando una variable no inicializada, aunque es opcional y es posible que deba activarla.

3

un puntero sin nueva está declarando algo sin memoria .. así que tienes que usar la nueva con el puntero. Sin embargo, Rectángulo rect; asignará de manera predeterminada la memoria.

para comprobar esto, hacer un constructor en la clase del rectángulo como,

void Rectangle 
{ 
    cout<<"Rectangle Constructor"; 
} 

a continuación, en el principal

Rectangle *rect; -->>O/P -- "Nothing" 
Rectangle rect2; -->>O/P -- Rectangle Constructor 
rect=new Rectangle; -->>O/P -- Rectangle Constructor 
0

El rectángulo comunicado *obj sólo significa que existe un puntero, que apuntará a la variable de tipo rectángulo

Con esta declaración que se acaba creando un puntero no la instancia del rectángulo objeto para el uso de este puntero se debe almacenar la dirección de la variable de tipo rectángulo en el puntero

Las dos maneras de hacerlo son por

obj=new rectangle; //variable is created in the stack storage 

o

rectangle r; 
obj =&r;  //variable is created in the heap storage 
+1

Creo que está invertida. el que tiene nuevo se crea en el montón y el segundo en la pila. – Aan

Cuestiones relacionadas