Is a Destructor Called When an Object Goes Out of Scope

Is a destructor called when an object goes out of scope?

Yes, automatic variables will be destroyed at the end of the enclosing code block. But keep reading.

Your question title asks if a destructor will be called when the variable goes out of scope. Presumably what you meant to ask was:

will Foo's destructor be called at the end of main()?

Given the code you provided, the answer to that question is no since the Foo object has dynamic storage duration, as we shall see shortly.

Note here what the automatic variable is:

Foo* leedle = new Foo();

Here, leedle is the automatic variable that will be destroyed. leedle is just a pointer. The thing that leedle points to does not have automatic storage duration, and will not be destroyed. So, if you do this:

void DoIt()
{
Foo* leedle = new leedle;
}

You leak the memory allocated by new leedle.


You must delete anything that has been allocated with new:

void DoIt()
{
Foo* leedle = new leedle;
delete leedle;
}

This is made much simpler and more robust by using smart pointers. In C++03:

void DoIt()
{
std::auto_ptr <Foo> leedle (new Foo);
}

Or in C++11:

void DoIt()
{
std::unique_ptr <Foo> leedle = std::make_unique <Foo> ();
}

Smart pointers are used as automatic variables, as above, and when they go out of scope and are destroyed, they automatically (in the destructor) delete the object being pointed to. So in both cases above, there is no memory leak.


Let's try to clear up a bit of language here. In C++, variables have a storage duration. In C++03, there are 3 storage durations:

1: automatic: A variable with automatic storage duration will be destroyed at the end of the enclosing code block.

Consider:

void Foo()
{
bool b = true;
{
int n = 42;
} // LINE 1
double d = 3.14;
} // LINE 2

In this example, all variables have automatic storage duration. Both b and d will be destroyed at LINE 2. n will be destroyed at LINE 1.

2: static: A variable with static storage duration will be allocated before the program begins, and destroyed when the program ends.

3: dynamic: A variable with dynamic storage duration will be allocated when you allocate it using dynamic memory allocation functions (eg, new) and will be destroyed when you destroy it using dynamic memory allocation functions (eg, delete).

In my original example above:

void DoIt()
{
Foo* leedle = new leedle;
}

leedle is a variable with automatic storage duration and will be destroyed at the end brace. The thing that leedle points to has dynamic storage duration and is not destroyed in the code above. You must call delete to deallocate it.

C++11 also adds a fourth storage duration:

4: thread: Variables with thread storage duration are allocated when the thread begins and deallocated when the thread ends.

Why We Say Destructor Call When Object Goes out of Scope?

An object which goes out of scope has its destructor called. That is an unchangeable guarantee which is mandated by the C++ language standard. It doesn't matter if you've manually called the destructor beforehand; when it goes out of scope, the destructor will be called. If you've written your destructor such that bad things happen if it's called twice, or if the extra behavior which the compiler inserts into the destructor code doesn't want to be called twice, bad things will happen.

This is one of many reasons why you should never manually call a destructor.

destructor not called for object going out of scope and end of main program

One of the golden rules of C++, if you use new on something, you also should delete it. When you use new, you are telling the compiler that you are now in charge of managing that variable's lifecycle.

destructor is not being called after object goes out of scope

This line actually declares a function, not a variable.

MyClass test();

If you were to change to uniform initialization syntax, you'd see two destuctor calls

MyClass test{};

or

auto test = MyClass();

C++ Destructor called for the wrong object?

Using the debugger, Created 2 and Destroyed 2 both display when the line x = Test(2); is called. If we just assigned x to Object 2, why is its destructor being called immediately? This follows on to the next part.

The line x = Test(2); first create a Test with the constructor argument 2. This is what produces Created 2. This nameless Test is then assigned to x which gives x.id the value 2. That nameless Test is then destroyed at the end of the expression, producing "Destroyed 2".

Secondly, since the destructor for Object 2 has been called, we can assume it has been destroyed. The next output of 2 seems to contradict this, as it suggests that x is still holding Object 2 (expected, but contradicted by the call of its destructor).

As expressed in the first part of this answer, it's not x that is destroyed but the temporary Temp. x.id is still valid and will yield it's new value, 2.

Finally, Destroyed 2 is outputted. This would make sense if we didn't see this earlier. Object 2 is stored in x, so when it goes out of scope the destructor is called.

This happens when x is destroyed at the end of the function. It's id value was changed to 2 by the previous assignment, so it produces "Destroyed 2".

1: Why is this weird behaviour occurring, and is there any logical reason to why it is?

It may not be the behavior you expected, but it's not weird. I hope this answer will help you understand why it's occurring.

2: Does 'overriding' an object (e.g. Object 1) with another object (Object 2) by assignment lead to its destructor (in this case the destructor of Object 1) to be called or not?

Assigning to an object does not destroy it. It replaces it's value with a new one and in that sense "destroys" the value it previously help but the actual object instance is not destroyed and the destructor is not involved.

Edit : It seems you may be concerned with resource leaks. Since no resources are being managed by Test there will be no leaks and the compiler generated members will behave fine. If your class does manage resources (usually in the form of dynamically allocated memory) then you will need to apply the rule of 3/5/0. Notably you will need to implement the assignment operator yourself such that it cleans up any previously held resources. It's not enough to implement just the destructor as it's not involved in assignment.

Is it true that destructors aren't called when a pointer instance of a class goes out of scope?

You only actually instantiated one object of type MyClass. That happened in this line:

MyClass Testvar;

In the following line, you only declared a pointer to an object of type MyClass, but this does not create a new object:

MyClass *ptrvar;

And in this line you assigned the address of your first MyClass to your pointer:

ptrvar = &Testvar;

So the pointer is addressing the very same object, you still have only one instance of MyClass. When the scope closes, TestVar is deleted, and you see the destructor called once.

You could have created a new MyClass object (on the heap) and assigned its address to your pointer like this:

MyClass *ptrvar = new MyClass();

Now you really do have two MyClass objects. However, when the scope closes you'll still see only one object being deleted. This is because new creates an object on the heap rather than on the stack, and such objects are not automatically deleted at the end of the scope in which they are created. You have to do this manually using delete:

delete ptrvar;

When this line executes, you'll see your destructor is called. If you don't do this you've left your object on the heap, and have "leaked" the memory it occupies.

To save having to do all of this manually, you should make use of the in-built smart pointers that C++ provides.

When is a C++ destructor called?

1) If the object is created via a pointer and that pointer is later deleted or given a new address to point to, does the object that it was pointing to call its destructor (assuming nothing else is pointing to it)?

It depends on the type of pointers. For example, smart pointers often delete their objects when they are deleted. Ordinary pointers do not. The same is true when a pointer is made to point to a different object. Some smart pointers will destroy the old object, or will destroy it if it has no more references. Ordinary pointers have no such smarts. They just hold an address and allow you to perform operations on the objects they point to by specifically doing so.

2) Following up on question 1, what defines when an object goes out of scope (not regarding to when an object leaves a given {block}). So, in other words, when is a destructor called on an object in a linked list?

That's up to the implementation of the linked list. Typical collections destroy all their contained objects when they are destroyed.

So, a linked list of pointers would typically destroy the pointers but not the objects they point to. (Which may be correct. They may be references by other pointers.) A linked list specifically designed to contain pointers, however, might delete the objects on its own destruction.

A linked list of smart pointers could automatically delete the objects when the pointers are deleted, or do so if they had no more references. It's all up to you to pick the pieces that do what you want.

3) Would you ever want to call a destructor manually?

Sure. One example would be if you want to replace an object with another object of the same type but don't want to free memory just to allocate it again. You can destroy the old object in place and construct a new one in place. (However, generally this is a bad idea.)

// pointer is destroyed because it goes out of scope,
// but not the object it pointed to. memory leak
if (1) {
Foo *myfoo = new Foo("foo");
}

// pointer is destroyed because it goes out of scope,
// object it points to is deleted. no memory leak
if(1) {
Foo *myfoo = new Foo("foo");
delete myfoo;
}

// no memory leak, object goes out of scope
if(1) {
Foo myfoo("foo");
}

Destructor Called Before Object Goes Out Of Scope

Problem:

If you create an object inside a block or function with automatic storage duration, like

{
// ...
EventListener myListener();
// ...
}

the object will be destroyed as soon as execution leaves the block/function, even though it may still be referenced from elsewhere. See also:

Creating an object: with or without `new`

Generally, you should never pass a pointer to an object with such scope anywhere where it might be stored internally.

Solution:

You'll have to explicitly use new if you want your object to live beyond the current block:

{
// ...
EventListener* myListener = new EventListener();
// ...
}

Im pretty sure the object is still in scope, because I can access its
members still.

Beware: A pointer to an object may still seem to be usable even after the object has been (implicitly) destroyed, but dereferencing this pointer is a severe, though not always obvious, bug.

C++ destructor called before lifetime of scope

Word curr_word = *curr_word_ptr; defines a local Word, that only lives in the local scope, your function. When the function exits, it is destroyed. Note it is a copy of the initial Word that is destroyed, not the original.

If you want handy syntax so you don't have to dereference all over, or make a copy, use a reference:

Word &word = *curr_word_ptr;

This is the syntactic sugar C++ provides to refer to an object without pointers (directly). Note though, any changes made to word will affect your original word as well in this case.

The problem is even worse if your Words contains dynamically allocated memory. Assuming you use the default copy constructor, the addresses will be copied. As such, destruction of a local Word will free memory still referenced by the original Word, causing a crash when next accessed.



Related Topics



Leave a reply



Submit