Reputation: 12533
I'm new to c++.
I've got a Rectangle
class. When I create a Rectangle
object like this:
Rectangle R1(10,10,90,20);
new
operator, would only then it be on the heap?(In general what would be the correct way to create an object in c++?)
To my understanding, if I create it without new
the object sits on the stack and does not need to be deleted at the end of its life time. And if do create it with new
Rectangle* R = new Rectangle(1,1,1,1);
it will be placed on the heap and would need to be de-allocated using delete
.
Upvotes: 0
Views: 109
Reputation: 66922
Rectangle R1(10,10,90,20);
This creates a variable with "automatic" duration. It is automatically destroyed when the code flow exits the scope. If it's not in a function, that means when the execution of your code completes. Usually (but not always) it sits on some sort of stack.
Rectangle* R = new Rectangle(1,1,1,1);
Rectangle* P(new Rectangle(1,1,1,1)); //rarely used
This part is confusing: The variable R
is a pointer with automatic duration (like above). It points at an Rectangle
with "dynamic" duration. Usually (but not always) the dynamic object sits on some sort of heap. The rectangle is destroyed only when you explicitly destroy it with delete R;
. This means if the function ends and there is no other copy of R
, it becomes impossible to delete, and will remain in memory until your program ends. This is called a memory leak.
In C++, dynamic memory is best handled with a smart pointer, such as std::unique_ptr
, so that you can't accidentally forget to delete it, even if the code is crashing.
std::unique_ptr<Rectangle> R(new Rectangle(1,1,1,1));
Upvotes: 4
Reputation: 477040
Lots of the things you say are either implementation details or dependent on the context. Consider this:
// file.cpp
Rectangle r1(1,2,3,4);
int main()
{
Rectangle r2 = r1;
Rectangle * r3 = new Rectangle(r1);
}
Here r1
has static storage and static (= permanent) lifetime, while r2
has automatic storage and automatic (= scoped) lifetime. That is, r1
constructed at program start and destroyed at the end (after main
returns), while r2
is constructed at declaration and destroyed at the end of its scope (i.e. the function body scope in this case).
The pointer r3
points to a Rectangle
object of dynamic storage and dynamic (= manual) lifetime. The object *r3
comes to life at the new
expression, and it will only be destroyed at the user's request via a matching delete
expression (or perhaps a manual destructor call). Since we don't destroy it, this is in fact a leak.
Nothing is known about the memory used by *r3
, other than that this memory is allocated by the static member function Rectangle::operator new()
if it exists, or otherwise by the global allocation function ::operator new
. The global version's memory is typically referred to as the "free store".
(All three objects r1
, r2
and *r3
are supposedly equal, since r2
and *r3
are constructed as copies of r1
.)
The situation gets even more interesting when you consider member variables: struct Foo { Rectangle r; };
.
Upvotes: 1
Reputation: 124642
R1
is created with automatic storage duration. This means that, in practice, it will be allocated on a stack-like structure. It doesn't have to be mind you, a 'stack' is just convenient and common. You have to call new
(or malloc
if you really want to for some silly reason... don't) to allocate memory dynamically.
See above.
Yes, anything you new
you must delete
. Typically a class will manage this for you. Take for example an std::vector<T>
. You allocate the vector
on the stack, but the internal data (i.e., an array of T) is allocated dynamically. When the vector
goes out of scope it delete []
s the dynamically allocated array for you in it's destructor, allowing you to remain pleasantly ignorant of the underlying memory management details.
Upvotes: 0