My question is actually two-part. A quick foreword: I am learning C++ and come from a C#/.NET background. Currently, I'm trying to understand object lifetimes and the results posted below don't make sense to me. I think it could have something to do with the creation of anonymous instances?
Question 1: Is it a good idea to dispose of all members in the destructor since it is possible that it is an "empty object" ?
Question 2: How do I prevent this? / How do I design my objects to work with this feature?
Question 3: Is this the "right" / "correct" way to do this?
Question 4: See comments in the very last bit of code
#include <stdio.h>
class A
{
public:
A()
{
printf("Constructor A\n");
}
~A()
{
printf("Destructor A\n");
}
};
class B
{
public:
B()
{
a = A();
printf("Constructor B\n");
}
~B()
{
printf("Destructor B\n");
}
private:
A a;
};
int main(int argc, char* argv[])
{
B b;
b = B();
printf("Done");
// Breakpoint
/*
Output:
Constructor A
Constructor A
Destructor A
Constructor B
Constructor A
Constructor A
Destructor A
Constructor B
Destructor B
Destructor A
*/
}
And another example that comes from a project I am currently working on.
#include <stdio.h>
class Mesh
{
public:
Mesh()
{
printf("Constructing Mesh with data %d\n", data);
}
Mesh(int d)
{
data = d;
printf("Constructing Mesh with data %d\n", data);
}
~Mesh()
{
printf("Destructing Mesh with data %d\n", data);
}
private:
int data = 0;
};
class Game
{
public:
Game()
{
printf("Game constructor\n");
}
~Game()
{
printf("Game destructor\n");
}
void init()
{
int cool_data = 3;
mesh = Mesh(cool_data);
}
private:
Mesh mesh;
};
int main(int argc, char* argv[])
{
Game game = Game();
game.init();
printf("");
// Breakpoint
/*
Output:
Constructing Mesh with data 0 <-- I assume this comes from the private member declaration in the Mesh class? So declaration means initialization?
Game constructor
Constructing Mesh with data 3 <-- Okay that's what I expected since I'm creating a new instance of the Mesh class with "3" passed in
Destructing Mesh with data 3 <-- Why is the instance we JUST created immediately being destructed?
*/
}
In your first example, we see a lot of construction and destruction of "A" objects that seems mysterious if you are not familiar with C++. Your B class has a private A variable "a". This object is default constructed when you first call the constructor to your B class. This is the very first "constructor A" print out that you see. The next print out is from the call to the A constructor here:
B()
{
a = A(); //A() calls the A constructor and returns an r-value
printf("Constructor B\n");
}
Assigning "a", an already instantiated object of class A, to the r-value returned by the call of the default constructor of class A causes you to print "Constructor A" when the r-value is created, and "Destructor A" when the r-value itself is destroyed. These behaviors can be changed by creating copy and move constructors/operators which will allow you to specify how these semantics operate. Check out this page: http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html or a book (C++ 11 primer is a good one) for more info on these operations.
Following the above logic, when you assign your created B object "b" to the B class default constructor's returned rvalue in the line:
b = B();
You construct a new B object, which must
1) construct an A object
2) create an A r-value
3) destruct the A r-value
4) construct a B object
The last two print statements are simply your B object being destructed as the main exits. The B object is destructed and so is it's member, the A object. Your first question seems to be about this behavior. It looks like you're asking whether you should destruct class members manually. This is only done in C++ if your class allocates memory for its members. If, for instance, instead of creating a local A object, your constructor in B did this:
B()
{
a = new A();
printf("Constructor B\n");
}
...
private:
A* a;
Then you would have to deallocate this A* in your destructor. As long as you are not allocating new memory using the new operator or otherwise, C++ will handle all other deallocation for you.
Your questions 2 and 3 are about how to prevent/work with object construction and whether or not a given way of constructing/destructing objects is right or wrong. I would like to point you to the rule of 0/3/5. This basically deals with how many constructors you should create for a given class. This is a pretty simple explanation of the rule http://en.cppreference.com/w/cpp/language/rule_of_three, but there are many others online.
Your last question has to do with the mesh class you have and why one of your variables is being destructed. Again, this has to do with the r-value returned by the call to the constructor. Basically, when you call your mesh constructor and assign its returned value to your variable "mesh" here:
void init()
{
int cool_data = 3;
mesh = Mesh(cool_data);
}
The mesh constructor returns an r-value which is an object of class Mesh with a data value of 3; The r-value is copied into your "mesh" variable and is promptly destroyed, leaving your "mesh" variable as an exact copy of it. Again, all of these behaviors can be changed by creating appropriate constructors and operators.
Related
It is said that constructor doesnot return anything.But if constructor doesnot return anything, then how do this code segment works:
*this=classname{args};.
I hope someone could shed me some light on whats actually going under the hood.
A complete code:
#include <iostream>
using namespace std;
class hell {
private:
int a{}, b{};
public:
hell(int _a = 7, int _b = 8) : a{ _a }, b{ _b } {}
void print() {
cout << a << endl << b << endl;
}
void change() {
*this = hell(4, 5);
}
};
int main() {
hell h;
h.print();
h.change();
h.print();
return 0;
}
The statement
*this = hell(4, 6);
does two things:
First it create a temporary and unnamed object of the class hell, initialized using the values you use to pass to a suitable constructor.
Then that temporary and unnamed object is copy-assigned to the object pointed to by this.
It's somewhat similar to this:
{
hell temporary_object(4, 5); // Create a temporary object
*this = temporary_object; // Copy the temporary object to *this
}
Your question must be about this line:
*this = hell(4,5);
This might look like a function call, calling the constructor function. But this is not a function call. This is (a particular) syntax for creating a new hell object, a temporary object. This is slightly outdated syntax, modern C++ prefers:
*this = hell{4, 5};
but it's the same thing.
This does call the constructor, but only as part of constructing a new object.
Once the temporary object gets constructed it gets assigned to *this. The End.
For better intuition, constructor can be called "initializator". This reveals more of it's main purpose. The constructor initializes object rather then creates. So the instance of the object is already present in the memory when the constructor is called. All it does is initializing it.
I want to initialize member object variables in the default constructor of the class.
Let's consider the following,
class ABC {
ABC(int A, int B) {
a = A;
b = B;
}
int a;
int b;
};
class Foo {
Foo();
ABC m_obj1;
};
From the above example, I would like to initialize "obj1" in "Foo::Foo()".
One of the restrictions I have is that I cannot do so in the initializer list, as I need to do some computation before I could initialize the member. So the option available (ASFAIK) is to do so in the body of the default constructor only.
Any inputs, how could I do this?
Edit: Restricting to C++11
Would this be a correct way,
Foo:Foo() {
int x = 10;
int y = 100;
m_Obj1(x, y); //Is this correct? <--------
}
Depending on your exact problem and requirements, multiple solutions might be available:
Option 1: Use a function to do the computations and call Foo constructor
Foo makeFoo()
{
// Computations here that initialize A and B for obj1 constructor
return Foo(A, B)
}
Option 2: Call a function that does the computations and initialize obj1 in Foo member initializer list
ABC initABC() {
// Some computations
return ABC(A, B)
}
Foo() : obj1(initABC()) {}
Option 3: Dynamically allocate obj1, for instance with a std::unique_ptr
Option 4: Use std::optional or an emulated c++11 version as shown by other answers
You simply call the base constructor inside the initializer list of the derived constructor. The initializer list starts with ":" after the parameters of the constructor. See example code!
There is no problem to call functions inside the initializer list itself.
int CallFunc1(int x) { return x*2; }
int CallFunc2(int y) { return y*4; }
class ABC {
public:
ABC(int A, int B):a{CallFunc1(A)},b{CallFunc2(B)} {
std::cout << "Constructor with " << a << " " << b << " called" << std::endl;
}
private:
int a;
int b;
};
class Foo {
public:
Foo(): obj1(1,2){}
Foo( int a, int b): obj1(a, b){}
private:
ABC obj1;
};
int main()
{
Foo foo;
Foo fooo( 9,10);
}
edit:
The best method I can think of for your case is a copy constructor, being more specific on what you need to store helps a lot since if it is just two ints inside a class dynamic allocation is not worth it, the size of the object being constructed makes a difference to what method is best, copy constructors can be slower with much larger data types as the object has to be created twice: once when it is automatically constructed in the parent objects constructor and again when a temporary object is created and all the values have to be copied, which can be slower then dynamically allocating if the size is larger.
As far as I'm aware all objects in a class are automatically initialized/allocated in the constructor so sadly dynamic memory use may be your best bet here.
If you are fine with having the object initialized but empty so you know it is not 'ready' yet you can later fill it with useful data when you would have wanted to initialize it. This can be done with default constructors that set the things inside the object to null values or something similar so you know the object hasn't been properly initialized yet. Then before using the object you can check whether it has been initialized by checking for the null values or by having put a bool in the object that tells you whether it is initialized. Dynamically allocated would still be better in my opinion and makes the code look cleaner overall as all you need to store is a null pointer until the object is needed and then allocated and set to the pointer. It is also very easy to check if the pointer is equal to nullptr to know the state of your object.
Dynamically allocating memory may be a hassle since you have to make sure to get rid of memory leaks and it is slightly slower than using the stack, but it is a necessary skill for c++ since the stack is not enough when making programs that use more than the few available megabytes of data on the stack so if you are doing this simply to avoid the hassle I recommend learning it properly. It would be nice if you could be more specific about what kind of object you want to do this with or if you just want an answer that works for most cases.
eg:
*ABC obj1 = nullptr;
...object is needed
obj1 = new(ABC(constructor stuff));
...obj1 isn't needed
delete obj1;
or c++ automatically deletes it when the program closes.
class A
{
int data;
public:
void display()
{
cout<<"Value is "<<data;
}
void set_data(int x)
{
this->data = x;
}
A object = new A();
};
When I run the above code, I get the error stating "new cannot appear in constant expression". Why is it so?
Operator new returns a pointer but A is not a pointer type. You want A*:
A* object = new A();
You also want to move the above statement outside your class body and place it into appropriate function such as main():
int main() {
A* p = new A();
// do work
delete p;
}
That being said you either don't need a pointer at all and you can simply use an object with automatic storage duration:
A object;
Or you want to consider using a smart pointer such as std::unique_ptr:
std::unique_ptr<A> p = std::make_unique<A>();
class A
{
public:
A * object = new A(); // In any case not: "A object = new A();"
};
Or:
class A
{
public:
A object;
};
-
See (let's assume, for a moment, that you don't get the error), in both cases, on the first construction of A object, it creates another A object as a data-member. This A data-member (let's call it object.object ) creates in its turn another A as its data-member (let's call it object.object.object), and so to infinity (or until no more memory). I mean, as a data-member, it can't be either as A* object = new A();, or as A object;
-
I am not sure what was your intention, but if you want to link one A-object to another A-object, the class should be something like that:
class A
{
public:
A * object = nullptr
};
you have to make object of class A into main().
void main(){
A object;
}
First of all, you cannot create an object in the class declaration. Class declaration is like a blue print of the class. It is to say these are the components of my class - variables and member functions. You cannot instantiate anything inside it as no memory is allocated during this stage.
Note that you can instantiate an object inside one of the member function including constructor. These are called during object creation when memory is allocated.
Even if you use this statement inside a constructor you will go into an infinite loop as the constructor calls its constructor and so on until you have memory overflow.
You can declare the object in main like this:
int main() {
A obj = new A();
//other operations
} //Object A is destroyed once you come out of main.
Or dynamically like this
int main() {
A* obj = new A(); //dynamic allocation
//other operations
delete obj; //explicitly destroy
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
Quick question,
I'm new to C++ and I'm having difficulty understanding the destructors.
I'll explain; lets say we have the following;
int _a;
a::a(int x) {
_a = x
}
then we have
a* a1 = new a(8);
I understand that a1's data is created on the heap, and a1 is a pointer, where I'm failing is with the destructor;
a::~a() {
// confusion here
}
Since _a is not a pointer since it was created implicitly on the heap thanks to new (correct) we cannot delete it so what do we do?
Does
delete a1;
call the destructor for a int automatically?
call the destructor for a int automatically?
That would be true if the object were a class type. For non-class types, there is no destrutor, not even implicitly defined ones. Hence, the question of calling the destructor does not arise.
Had your code been something like:
struct Foo
{
Foo() {}
~Foo() {}
};
struct a
{
Foo f
};
a* aptr = new a;
delete aptr;
The destructor, Foo::~Foo(), will be called for f.
I understand what you're driving at and the answer is no, C++ destructors do not automatically destroy the data that your class contains. Unfortunately your example is too contrived to highlight the problem well. int is a primitive type so its destruction is primitive (someone might want to comment on what actually happens in ints destructor). Take the following example:
class A
{
public:
int x;
~A()
{
std::out << "in A destructor" << std::endl;
}
};
class B
{
public:
A* x;
B()
{
x = new A();
}
~B()
{
std::out << "in B destructor" << std::endl;
// does not automatically delete x
}
};
auto x = new B();
delete x;
In this example, constructing an instance of B will also construct an instance of A because you explicitly new it up in the constructor of B. However, unless you explicitly delete x in your destructor for B it will not automatically be deleted.
A slight variation of me previous example would be if B::x were of type A and not A*, in which case the answer is yes, the destructor for A would be called.
I hope this helps!
The destructor is just a function that is called automatically when the instance comes out of scope. It's a convenient way to release dynamically allocated memory.
You don't have to worry about releasing variables that were allocated on the stack (anything that is declared and not new-ed).
For example:
int localStackVar = 5; //no need to deallocate explicitly
int* localPointer = &localStackVar // no need to deallocate explicitly
int* heapValue = new int(); //Allocates to the heap so you need to call delete explicitly
The first two from the example above are on the stack, the first one is an int and the second is an int pointer, which is just a way to say it's a variable that holds the memory address of another variable.
Both of those will be deallocated automatically, since you did not call new on them.
The third line allocates an int on the heap. You have to call delete on it when you don't need it anymore.
If those 3 variables were a part of a class, your constructor and destructors would look like this:
MyClass::MyClass()
{
heapValue = new int();
}
MyClass::~MyClass() //destructor
{
delete heapValue;
}
void someFun()
{
MyClass instance; //constructor is called here
//do stuff
return; //destructor is called here
}
So while MyClass instance is a local stack variable when declared in someFun
since the constructor is called automatically, heapVal is made to point to a memory location that is on the heap which needs to be released explicitly.
If your destructor did not call delete on it, the memory would "leak" it will not be released until your program terminates.
myClassVar = MyClass(3);
I expected destructor being called on the previously created myClassVar on the left.
But it is actually being called on the new object that's created by MyClass(3).
My full test code and output follows..
edit
How do I fix the problem?
Implement an assignment operator?
MyClass actually has pointers, and MYSQL_STMT*, I wonder how should I deal with MYSQL_STMT* variable.
I just need MyClassVar(3) object not the MyClassVar() which was first created when ClientClass object was created.
I came across this situation fairly often, and wonder if there's a good way to do it.
#include <stdio.h>
class MyClass
{
public:
MyClass() { printf("MyClass %p\n", this); }
MyClass(int a) { printf("Myclass(int) %p\n", this); }
~MyClass() { printf("~MyClass %p\n", this); }
private:
int mA;
};
class ClientClass
{
public:
void Foo()
{
printf("before &myClassVar : %p\n", &myClassVar);
myClassVar = MyClass(3); // this is the important line
printf("after &myClassVar : %p\n", &myClassVar);
}
private:
MyClass myClassVar;
};
int main()
{
ClientClass c;
c.Foo();
return 0;
}
MyClass 0x7fff5fbfeba0
before &myClassVar : 0x7fff5fbfeba0
Myclass(int) 0x7fff5fbfeb70
~MyClass 0x7fff5fbfeb70 // <--- here destructor is called on the newly created object
after &myClassVar : 0x7fff5fbfeba0
~MyClass 0x7fff5fbfeba0
Here's how the critical line breaks down:
myClassVar = MyClass(3);
First, MyClass(3) calls constructor and returns the object.
Second, myClassVar = copies the object to myClassVar.
Then the statement ends. The object (which is an immediate) is dead, and thus the destructor is invoked.
EDIT :
As for how to get around this. The only way I can think of is to use a placement new. I'm not sure if there's a better solution other than making a "set" method.
myClassVar = MyClass(3);
myClassVar continues to exist after this line. The lifetime of MyClass(3) ends at the semicolon.
As the other posts mentioned the object with the custom constructor MyClass(3) gets destroyed after the assignment operation myClassVar = MyClass(3). In this case you do not need a custom assignment operator because the compiler generated one copies the member mA to the already existing object myClassVar.
However since MyClass defines its own destructor you should adhere to the rule of three, which mandates that in such a case you should implement a custom assignment operator as well.
Responding to your edit: how do you fix what problem? It's not clear
what the problem is. If your class needs a destructor (and there's no
polymorphism in play), it probably needs both an assignment operator and
a copy constructor. Similarly, when "tracking" construcctions and
destructions, you should probably provide both as well, since they will
be called.
Otherwise: if the problem is that you're constructing and then
assigning, rather than constructing with the correct value immediately,
the simple answer is "don't do it". The compiler does what you tell it
to. If you write:
MyClass var;
var = MyClass(3);
you have default construction, followed by the construction of a
temporary, assignment, and the destruction of the temporary. If you
write:
MyClass var(3);
or
MyClass var = 3;
you only have one construction. (Note that despite appearances, there
is no assignment in the last snippet. Only construction.)
For class members, this difference appears in the way you write the
constructor:
ClientClass::ClientClass() { var = MyClass(3); }
is default construction, followed by creation, assignment and
destruction of a temporary;
ClientClass::ClientClass() : var( 3 ) {}
is just construction with the correct value. (Rather obviously, this
second form is preferred.)