C++ need clarification about destructors and scope - c++

I have a problem, and I'm pretty sure I know the cause of it. I'd just like some clarification. I have a class that contains other classes, but I'll limit my example to two classes for simplicity.
Class A contains class B. In class A's constructor, it initializes class B by calling B's constructor. At the end of class A's constructor, class B's destructor gets called, which wasn't the behavior I was expecting. Here's an example...
a.h
#include "b.h"
class a {
public:
b classB;
a(int someParam);
};
a.cpp
#include "a.h"
//Class A's constructor
a::a(int someParam) {
//Set class B by calling it's constructor
classB = b(someParam);
//Now class B's destructor gets called when exiting A's constructor...
}
I know that if you declare a variable without using "new", it gets destroyed when it leaves the current scope. But I always thought that applied to the variable's scope, and not to the scope at which you assign a value to it. That is the problem, right? If it is, there's nothing wrong with doing classB = *new b(someParam); is there? Or should I just use pointers instead?

In this line:
classB = b(someParam);
The expression b(someParam) creates a temporary, nameless b object, which is then asssigned to the member object, classB. It is the destructor of this nameless temporary which is called, not the destructor of your member object. If you want avoid the creation of this temporary, and instead directly initialize your member object with the appropriate constructor, use the initialization list:
a::a(int someParam)
:classB(someParam)
{}
And this:
classB = *new b(someParam);
Is an instant memory leak. You're allocating an object on the free store, copy assigning from it to classB, and losing the pointer.

Related

Destruction order of class data members?

Imagine a class like this:
class foo {
public:
foo() : _bar{new bar}, _baz{new baz} {}
private:
unique_ptr<bar> _bar;
unique_ptr<baz> _baz;
};
So whenever an instance of foo gets destructed, then in what order will the data members of it be destroyed, if that's defined behavior at all?
Let's say that _baz does depend on the existance of _bar, maybe it uses some resource that _bar owns (let's assume it knows about the _bar object, even though the constructor doesn't reflect this).
So in this case, if _bar gets destructed first (when its time to destruct foo), then _baz could potentially try to access some resource which has been freed by _bar's destructor.
An obvious solution is to implement a destructor in foo, which manually frees _baz and _bar in the right order, but what if there's no destructor implemented? Is there a default behavior that defines the destruction order of data members?
The order of destruction of data members is the reverse of their order of declaration, the same way as variables declared within a scope:
{
// a, b constructed in that order
bar a;
baz b;
} // b, a destroyed in that order

C++ Class Output [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 9 years ago.
i would love to understand how this one works!
if i have this code for example
class myclass
{
public :
int a;
myclass(){a=0; cout<<"first"<<endl;}
myclass(int i){a=i;cout<<"second"<<endl;}
~myclass(){cout<<a<<endl;}
};
class yourclass:protected myclass
{
int x;
myclass m1;
public:
myclass m2;
yourclass (int i): m2(3),myclass(i){x=i; a=7;}
}
and i'll make an object like this
yourclass ob1(5);
can you please explain how to works? how to calls constructors ?
Thank you
When you declare an object of a class myclass like this:
myclass ob1(5);
it means that you've created it with the second constructor which accepts int parameter. In other words, you literally called the second constructor. By the way the object is created on stack.
When you declare an object of a class myclass like this:
myclass ob1;
it means that you've created it with the first constructor which is parameterless. The right term for parameterless constructor is default constructor. In other words, you literally called the default (the first one) constructor. By the way the object is created on stack too (as in the previous case).
When objects are created on stack they are destructed automatically when the object goes out of scope. The notion of scope applies to the blocks of code which include functions/methods/blocks. You can easily distinguish the block by a pair of curly brackets {}. For example:
void function() {
myclass ob1;
} // <--- think of ob1 being destructed at this point
the object ob1 will go out of scope when function finishes execution and accordingly the destructor for ob1 is automatically called. Another example:
void function() {
while(true) {
myclass ob1;
} // <--- think of ob1 being destructed at this point
// ob1 does not exist here!
}
notice the infinite loop and the object ob1 created inside it on every iteration. You can clearly see that curly brackets define a block which can combine multiple statements that constitute each iteration (currently there is only 1 statement). Accordingly, the object ob1 will be automatically destructed in the end of each iteration.
The notion of scope applies to class members too. For instance, say you have a class wrapper, and you declare myclass as its member (m1) in the following way:
class wrapper {
public:
myclass m1;
};
Then lets take one of the previous examples and create an object of wrapper on stack:
void function() {
wrapper w;
} // <--- destructor of w called first, destructor of w.m1 is called after
First the execution of the default constructor of w is started, during which w.m1 is created (with default constructor in this case because I didn't specify in the constructor of w which constructor of w.m1 I'd like to call). Then the constructor of w finishes the execution, and w can be deemed as officially created. The execution of function continues.
When function finishes execution, w goes out of scope, and as you remember its destructor is called automatically then. As soon as the destructor of w finishes the execution, the destructor of w.m1 is automatically called too. You can think of it as the object w has its own internal scope while it's alive, and a soon as it dies, all of its members go out of scope and should die too.
Ok, let's take it easy and analyze it step by step.
First class
class myclass {
public :
int a;
myclass(){a=0; cout<<"first"<<endl;}
myclass(int i){a=i;cout<<"second"<<endl;}
~myclass(){cout<<a<<endl;}
};
Here we are defining a class myclass which have a single member variable a of type int. It declares a default constructor (with no arguments) which assigns to a, 0 and then proceed to print first.
We also have a one-parameter constructor that initialize a to that first parameter, and prints second, and a destructor which simply prints the value of the member variable a before deallocating it.
Initialization list
Now, within constructors you can define an initialization list which is on the form
<class name>(...) a(x), b(y), c(z), ... {}
// ^^^^^^^^^^^^^^^^^^^^^
This initialization list is necessary when there's no default constructor available for the type of any member variable of the class. Suppose we create a nogood class without a default constructor and define our main class to have a member of type nogood, how would he initialize that member variable? You can expect it to wait until the constructor body is executed.
Second class
class yourclass : protected myclass {
int x;
myclass m1;
public:
myclass m2;
yourclass (int i): m2(3),myclass(i){x=i; a=7;}
};
Now yourclass inherits protected from myclass. What does it means? It means that whatever in myclass is public or protected, will be protected in yourclass (whatever is private will still be private).
The class yourclass defines two private members x and m1 and one public member m2. It doesn't define any default constructor for it and defines a single parameter constructor instead (that can actually be also used to implicitly convert an int to yourclass if required).
Output: constructors
Firstly it calls the protected sub object's constructor producing second.
Then, since we haven't initialize m1 explicitly, it will initialize it with the default constructor producing the output first.
Finally in the constructor we initialize m2(3) which is of type myclass which will call myclass::myclass(int) producing second as output. So the output is:
second
first
second
Output: destructors
Now for the destructors calls, it will call the destructors for each member variables in the reverse order to their initialization. The order of initialization was: m1, m2. The reverse order is m2, m1. m2 was initialized with 3 in the initialize list, m1 was initialized to 0 by default. Then finally it calls the ob1 destructor which was initialized to 7. Therefore the final output is:
second
first
second
3
0
7

Destruction of non-pointer members of a class

When is a non-pointer member of a class destructed? Example:
class foo {
private:
int a;
public:
foo(int sa):a(sa){}
~foo(){}//does anything need to be done here?
};
{
foo(10);
}//the destructor is called
Should anything be done inside the destructor? Thanks!
No, not a thing. a will be destroyed after any code in your destructor completes. In a case like this, you don't even need to declare a destructor; the compiler will do the right thing on its own.
An object's contents are destroyed in inverse order of their appearance in the class definition after the execution of the object's destructor.
A non-pointer member of an object is destructed after the containing object's destructor has completed.

Base class's destructor called without destroying the base class!

#include<iostream>
using namespace std;
class A
{
public:
int i;
A() {cout<<"A()"<<endl;}
~A() {cout<<"~A()"<<endl;}
};
class B:public A
{
public:
int j;
B(): j(10)
{
this->i=20;
this->~A();
}
};
int main()
{
B abc;
cout<<"i="<<abc.i<<" j="<<abc.j<<endl;
}//main
Two questions:
How come A's destructor gets called like an ordinary function instead of destroying the object? (or is it some kind of rule that the base class will be destroyed only if the child class's destructor calls the base class's destructor?) I was trying out this sample code to find out how the destructor works. So if simply calling the destructor function does not destruct the object, then there is obviously some other kind of call that calls the destructor and only then the object is destructed. What's so special in that kind of call and what call is it?
Is there a way to have an initialization list for A in B's constructor? Something like this:
class B:public A
{
B(): j(10), A():i(20) {}
};
Destructor is like any other normal function which you can call (but you should never do it unless you use a placement new). When you call delete on a object two things happen: Destructor is called for cleanup and then operator delete is called to release the memory allocated for the object. Here the second step is not happening.
No, you can not call it like that. What you can do is some thing like this:
class A
{
public:
A(int n) : i(n){}
};
class B : public A
{
public:
B() : A(20), j(10){}
};
The base class's destructor should be virtual. Here, as it's created on the stack, it's not problem, but anyway..
No, but you can call the class A() constructor in the initialize list of B's constructor, like this:
B(): A( .. ), ...
A* a = new B();
//..
delete a;
will not call B's destructor unless class A destructor is virtual. That's why STL containers should not be derived - theirs destructors are not virtual.
#Nav: no, your understanding of "destroyed" is just wrong. When an object's destructor is called, the object is destroyed. You seem to believe that the memory it resided in evaporates entirely, but that never happens. The object no longer exists, but some garbage data is typically left over by the object, and if you're willing to break the rules of C++ and invoke undefined behavior, then you can read those leftover bytes, and they'll look like the object, and because there are no runtime checks on whether you're accessing a valid object, you can often treat them as an object. Which you do.
It's illegal, it's undefined behavior, but in practice it often works.
Once again, a destructor does not physically vaporize the memory. Your RAM still has the same capacity after a destructor has executed. Conceptually, the object no longer exists once the destructor has run. But the data it contained is still there in memory.
For point:
This is an undefined behaviour but only ~A() is called though an instance of class B because ~A() is not declared virtual. See more on Wikipedia.
No. For derived classes, first call your parent class, then assign parameters.
For point 1) on Wikipedia:
having no virtual destructor, while
deleting an instance of class B will
correctly call destructors for both B
and A if the object is deleted as an
instance of B, an instance of B
deleted via a pointer to its base
class A will produce undefined
behaviour.
Example (for point 2):
B(): A(), j(10) {}
or
B(): A() {j = 10;}
1) Destructor calling order in C++ is reverse order of the constructor calling order. So first derived class object get destroy and then base class object.
2) No.
In the code that you are giving, you are indeed destroying the base class and as such i. Calling a destructor and then using the dead object is undefined behavior - it may work or it may crash.
Should i was something that is more complex that an int (for example a vector), trying to do anything with that would probably result in a crash.
If you call ~SomeClass() yourself, explicitly, the destructor function will be called. Which leaves the object (in this case, the base class part of the object) in a destroyed state.
Since the destructor is not virtual, the destructor of derived classes will not be called, but base classes of SomeClass will be destroyed too.
Trying to find out if A is really destroyed by just using the i member, is not a good test. In fact, you can't test this, since using the object results in undefined behavour. It may work, or it may not (in your case, it probably will print "i=20 j=10", but i is already destroyed).

When are member data constructors called?

I have a global member data object, defined in a header (for class MyMainObj) like this.
class MyMainObj
{
MyDataObj obj;
}
MyDataObj has a default constructor.
When is the constructor for MyDataObj called?
Is it called as part of the creation of MyMainObj?
MyDataObj in this case is not a member of MyMainObj, it's a local variable.
But, constructors for data members are called in your class's constructor. The default constructor for every member is called before execution reaches the first line in the constructor, unless you explicitly specify a constructor using an initializer list, in which case that constructor is called instead.
With that code, obj isn't a member of MyMainObj -- it's simply a local object inside that constructor. As such, it'll only be constructed when/if that constructor is invoked.
Concerning your code, you have a function with a variable inside. Upon entering the function, you will run to the line of code that declares the variable, and the constructor will be run then.
But you say "creation of MyMainObj". It's a function, it can only be called, not created.
This is all concerning the title question, "when are members constructed?" This would apply if MyMainObj was a class and not a function.
Your member objects are constructed in the order of which they appear in the class declaration. All objects are full constructed upon entering the constructor. (But this does not include the class itself!)
That is to say, by the time the class enters its constructor, all the members have finished their constructor.
Objects are destructed in reverse order, in the destructor (after the destructor is run).
In a pseudo-diagram:
MyClass
Member1
Member2
Member3
Construction:
Member1
Member2
Member3
MyClass
Destruction:
MyClass
Member3
Member2
Member1
You can manually call the members constructor using an initialization list:
class foo
{
public:
foo(void) : i(0) // construct i with 0.
{
}
int i;
};
There are various question on SO about initialization lists. Initialization list order, Copy-construction initialization list, and more.
Yes, the constructor would be called whenever a MyMainObj instance is created.
I'm a bit confused by the "global member" terminology - the way you've declared that object it would be a local variable inside the constructor. Am I missing something here?
Yes, as other stated the member will be created on the owner class creation, on construction (be it generated by the compiler or with a provided constructor).
The order of creation will be the same as how your members apear in the class declaration. For example :
class MyType
{
Thing a;
Thing b;
Thing d;
Thing c;
};
Whatever constructor is used, whatever the order in a initialization list, the members will be constructed in this order : a, b, d, c. Once it's all done, the constructor code will be executed (if it exists) and only then your whole object will be constructed.
Upon entering an object constructor, memory has already been allocated for it. Then the execution order is as follows:
Base class constructor, if any, as specified in the initialisation list; if not specified, the default constructor is used.
The constructors for the member data, as specified in the initalisation list (default if not specified), in the order they are declared in the class definition. The order in which they are specified in the initialisation list is irrelevant.
The constructor body.
In the example set in the question, the first thing that would be executed upon entering the default constructor of MyMainObj would be the default constructor of MyDataObj to construct the member data obj.
Given a class A:
class A {
MyDataObj obj;
}
If you don't write the constructor for A, the compiler will create one for you, which will create obj as part of constructing A (and destroy obj as part of destroying A.
If you do write a constructor for A, then obj will be created before your constructor runs, although you can reassign it:
class A {
MyDataObj obj;
public:
A() { } // obj created, but the value may or may not be predictable
}
class AA {
MyDataObj obj;
public:
AA()
{
obj = MyDataObj(5);
}
}
class AAA {
MyDataObj obj;
public:
AAA() : obj(5) { } // member initializer list, my preferred method
}
With the third option, the data objects are created before the member initializer list runs, and the values are assigned in the order they are declared in AAA, NOT the order they are listed in the member initializer list.
UPDATE: There is a difference between creation and initialization. Space for the data members (and the base classes, and the data members for the base classes) is always set aside -- which I would call "creation." However, that doesn't mean a useful value is stored in that memory. There are separate rules for whether an object is default initialized, which depend on the type of the data member (primitive, POD, non-POD) and, IIRC, the storage class of the main object (local, static, global). The easiest way to avoid surprises in this area is to simply make sure you explicitly initialize everything.