Initializing an object with and without new operator
-
07-03-2021 - |
Question
If I have a class Rectangle
class Rectangle{
private:
double width;
double height;
public:
void Set(double w , double l){
width = w;
height = l;
}
};
and I decleare an object such:
Rectangle *Obj;
and then try to initialize its properties:
Obj->Set(3,5);
the compiler shows at run-time: The variable 'Obj' is being used without being initialized.
The problem can be solved by:
Rectangle *Obj=new Rectangle;
I would ask about the reason! And why the compiler doesn't show any error at compiling time?
La solution
Rectangle *Obj;
just defines a pointer to an object of class Rectangle
. Defining a pointer does not reserve any memory for the object itself, just for the pointer. Thus, if you access the pointer, you will likely end up at an address in memory that doesn't even belong to your process. However, the compiler cannot know that you haven't initialized the pointer (the keyword here is aliasing) and hence cannot output an error message.
The solution is either using new
like you suggested, or declare an instance of Rectangle
like so:
Rectangle Obj;
which will call a default constructor. You can then set your members using
Obj.Set(3, 5);
Autres conseils
and I decleare an object such:
Rectangle *Obj;
Wrong, this declares a pointer, not an object. Pointers have to be initialized either using new
or by assigning them the address of an existing object.
Mmm a bit of confusion there:
the compiler shows at run-time: The variable 'Obj' is being used without being initialized
That is what you'd call compile time. Just straightening out the jargon.
Also, the simplest way would be to
Rectangle Obj;
Obj.Set(3,5);
which is sufficient for most scenarios, except dynamic allocations, or polymorphic containers:
std::vector<Shape*> v;
v.push_back(new Rectange());
v.back()->Set(3,5);
v.push_back(new Circle());
v.back()->Set(3,5);
//
Although whenever using new
you should be remembering to delete
as well. This can be quite a nightmare (in the light of exceptions, too). I suggest:
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);
With Rectangle *Obj;
, you are declaring a pointer to a Rectangle, but you haven't told Obj
to which Rectangle it should point. You might set or instantiate Obj
later on to an existing Rectangle
or only if you require.
C++ is all about giving you precise control over your memory and performance. In fact, that's why it is used in some embedded environments! Automatically instantiating Obj
poses several "issues"
- When do we free
Obj
? - Who frees
Obj
? - What about the performance implications of creating a
Rectangle
on the heap? - Is this an environment in which we have enough resources (memory, CPU, etc) to even create the Rectangle, especially if it is large.
- Do you pass the address of
Obj
somewhere and then instantiate it at runtime through some complex method that we can't statically analyse?
What you do isn't a syntax error, which is what compilers throw errors on -- errors when compiling. An analyser (one is built into Visual Studio 2010 professional) might warn you that you're using an uninitialized variable, though that is optional and you may need to turn it on.
pointer without new is declaring something without memory .. SO u have to use new with pointer. However Rectangle rect; will defaultly allocate the memory .
to check this, make a constructor in Rectangle class like,
void Rectangle
{
cout<<"Rectangle Constructor";
}
then,in main
Rectangle *rect; -->>O/P -- "Nothing"
Rectangle rect2; -->>O/P -- Rectangle Constructor
rect=new Rectangle; -->>O/P -- Rectangle Constructor
why the compiler doesn't show any error at compiling time?
Because, it's syntactically correct. However, such statements will lead to undefined behavior, smart compilers will always issue warning.
In g++ you can turn such kind of compiler warning in errors.
The statement rectangle *obj
just means that there exist a pointer, that will point to the variable of type rectangle.
With this statement you are just creating a pointer not the instance of the object rectangle for the usage of this pointer you must store the rectangle type variable's address in the pointer
The two ways of doing it are by
obj=new rectangle; //variable is created in the stack storage
or
rectangle r;
obj =&r; //variable is created in the heap storage