Onedayitwillmake
Onedayitwillmake

Reputation: 711

Confused about C++ memory deallocation

So in C++ if I create an object useing new I should always deallocate it using delete
For example

Segment::Segment(float length)
{
    segmentLength = length;

    angle = 0.0f;
    x = Rand::randFloat(1.0f, 1.5f);
    y = Rand::randFloat(1.0f, 1.5f);

    vx = Rand::randFloat(0.0f, 1.0f); 
    vy = Rand::randFloat(0.0f, 1.0f);
    prevX = Rand::randFloat(0.0f, 1.0f);
    prevX = Rand::randFloat(0.0f, 1.0f);
};

And lets say I use it like this in another class such as,

this._segmentObject = Segment(2.0f);
this._segmentPointer = new Segment(2.0f);

In the destructor of that class, I know I should call delete on the this._segmentPointer, however how do I make sure memory is deallocated for the other one?

Upvotes: 1

Views: 267

Answers (7)

Jason
Jason

Reputation: 32490

The destructors for all class-type member objects are called at the time of the destruction of the primary class. So your this object, which is allocated on the stack, will have it's destructor called when it goes out-of-scope. At that time, any class-type member objects of your this object will have their own destructors called in addition to the destructor for your this object which will call delete on the member pointer.

For instance, take the following code sample:

#include <iostream>

using namespace std;

class A
{
        public:
                A() {}
                ~A() { cout << "Destructor for class A called" << endl; }
};

class B
{
        private:
                A a;

        public:
                B() {}
                ~B() { cout << "Destructor for class B called" << endl; }
};

int main()
{
        B b;
        return 0;
}

When run, the output becomes the following:

Destructor for class B called  
Destructor for class A called

So you can see that when b, which is allocated on the stack, goes out-of-scope at the end of main, the destrutor for class B is called, which in-turn, after executing the body of the destructor function, calls the destructors for any of its class-type member data objects, which in this case would mean the destructor for class A. Therefore in your case, the pointer would have delete called on it in the destructor for your this class, and then the destructor for _segmentObject would be called after the destructor for this had completed execution of the body of its destructor. Then once all the destructors for the non-static data-member objects had been called, the destructor for this then returns.

Upvotes: 1

Peter K.
Peter K.

Reputation: 8108

As others have said, you don't need to explicitly do anything to reclaim the memory used by this._segmentObject. As soon as it goes out of scope, the memory will be reclaimed.

It's not clear why you would use Segment in both ways. You should try to ensure you use the Resource Acquisition Is Initialization idiom, as it removes much of the need for checking new / delete pairs. That is, just use the this._segmentObject version, not the pointer.

Your application may not allow it, though.

Upvotes: 0

Konrad Rudolph
Konrad Rudolph

Reputation: 545508

however how do I make sure memory is deallocated for the other one?

It is automatically. This is why this type of storage is called automatic. Automatic storage is released at the end of the storage’s life cycle, and the objects’ destructors called.

The object life-cycle ends when the program control leaves the scope where the object has been allocated.

Upvotes: 5

Evan Teran
Evan Teran

Reputation: 90422

Things not allocated with new, new[] or the malloc family should be destructed and "freed" when the object goes out of scope.

Often this simply means that that the code has reached the end of the block it was declared it or that the object that it was in was destructed (one way or another).

To see this in action, you can do something like this:

struct C {
    C()  { std::cout << "C()" << std::endl; }
    ~C() { std::cout << "~C()" << std::endl; }
};

struct B {
    B()  { std::cout << "B()" << std::endl; }
    ~B() { std::cout << "~B()" << std::endl; }
private:
    C c_;
};

struct A {
    A()  { std::cout << "A()" << std::endl; }
    ~A() { std::cout << "~A()" << std::endl; }
};

int main() {
    B *b = new B; // prints "B()", also constructs the member c_ printing "C()"
    { // starts a new block
        A a; // prints "A()";
    } // end of block and a's scope, prints "~A()"

    delete b; // prints "~B()", also destructs member c_, printing "~C()"
}

Note: that if we did not do delete b, the "~B()" and "~C()" would never print. Likewise, if c_ were a pointer allocated with new, it would need to be delete'd in order to print "~C()"

Upvotes: 4

piotr
piotr

Reputation: 5787

Not only that, You should only allocate with new and deallocate with delete in Constructors or Destructors, otherwise your program can leak if an exception is thrown.

Upvotes: 1

antlersoft
antlersoft

Reputation: 14786

The memory for this._segmentObject is part of the memory of the containing object, and will be released when the containing object is destroyed.

this._segmentObject is assigned from a temporary object that is created on the stack and deleted when it goes out of scope.

Upvotes: 3

Max
Max

Reputation: 3180

The _segmentObject is allocated automatically on the stack. The object destructor will be called automatically when the variable gets out of scope.

Upvotes: 0

Related Questions