Related
I have a simple C++ code, but I don't know how to use the destructor:
class date {
public:
int day;
date(int m)
{
day =m;
}
~date(){
cout << "I wish you have entered the year \n" << day;
}
};
int main()
{
date ob2(12);
ob2.~date();
cout << ob2.day;
return 0;
}
The question that I have is, what should I write in my destructor code, that after calling the destructor, it will delete the day variable?
Rarely do you ever need to call the destructor explicitly. Instead, the destructor is called when an object is destroyed.
For an object like ob2 that is a local variable, it is destroyed when it goes out of scope:
int main()
{
date ob2(12);
} // ob2.~date() is called here, automatically!
If you dynamically allocate an object using new, its destructor is called when the object is destroyed using delete. If you have a static object, its destructor is called when the program terminates (if the program terminates normally).
Unless you create something dynamically using new, you don't need to do anything explicit to clean it up (so, for example, when ob2 is destroyed, all of its member variables, including day, are destroyed). If you create something dynamically, you need to ensure it gets destroyed when you are done with it; the best practice is to use what is called a "smart pointer" to ensure this cleanup is handled automatically.
You do not need to call the destructor explicitly. This is done automatically at the end of the scope of the object ob2, i.e. at the end of the main function.
Furthermore, since the object has automatic storage, its storage doesn’t have to be deleted. This, too, is done automatically at the end of the function.
Calling destructors manually is almost never needed (only in low-level library code) and deleting memory manually is only needed (and only a valid operation) when the memory was previously acquired using new (when you’re working with pointers).
Since manual memory management is prone to leaks, modern C++ code tries not to use new and delete explicitly at all. When it’s really necessary to use new, then a so-called “smart pointer” is used instead of a regular pointer.
You should not call your destructor explicitly.
When you create your object on the stack (like you did) all you need is:
int main()
{
date ob2(12);
// ob2.day holds 12
return 0; // ob2's destructor will get called here, after which it's memory is freed
}
When you create your object on the heap, you kinda need to delete your class before its destructor is called and memory is freed:
int main()
{
date* ob2 = new date(12);
// ob2->day holds 12
delete ob2; // ob2's destructor will get called here, after which it's memory is freed
return 0; // ob2 is invalid at this point.
}
(Failing to call delete on this last example will result in memory loss.)
Both ways have their advantages and disadvantages. The stack way is VERY fast with allocating the memory the object will occupy and you do not need to explicitly delete it, but the stack has limited space and you cannot move those objects around easily, fast and cleanly.
The heap is the preferred way of doing it, but when it comes to performance it is slow to allocate and you have to deal with pointers. But you have much more flexibility with what you do with your object, it's way faster to work with pointers further and you have more control over the object's lifetime.
Only in very specific circumstances you need to call the destructor directly. By default the destructor will be called by the system when you create a variable of automatic storage and it falls out of scope or when a an object dynamically allocated with new is destroyed with delete.
struct test {
test( int value ) : value( value ) {}
~test() { std::cout << "~test: " << value << std::endl; }
int value;
};
int main()
{
test t(1);
test *d = new t(2);
delete d; // prints: ~test: 2
} // prints: ~test: 1 (t falls out of scope)
For completeness, (this should not be used in general) the syntax to call the destructor is similar to a method. After the destructor is run, the memory is no longer an object of that type (should be handled as raw memory):
int main()
{
test t( 1 );
t.~test(); // prints: ~test: 1
// after this instruction 't' is no longer a 'test' object
new (&t) test(2); // recreate a new test object in place
} // test falls out of scope, prints: ~test: 2
Note: after calling the destructor on t, that memory location is no longer a test, that is the reason for recreation of the object by means of the placement new.
In this case your destructor does not need to delete the day variable.
You only need to call delete on memory that you have allocated with new.
Here's how your code would look if you were using new and delete to trigger invoking the destructor
class date {
public: int* day;
date(int m) {
day = new int;
*day = m;
}
~date(){
delete day;
cout << "now the destructor get's called explicitly";
}
};
int main() {
date *ob2 = new date(12);
delete ob2;
return 0;
}
Even though the destructor seems like something you need to call to get rid of or "destroy" your object when you are done using it, you aren't supposed to use it that way.
The destructor is something that is automatically called when your object goes out of scope, that is, when the computer leaves the "curly braces" that you instantiated your object in. In this case, when you leave main(). You don't want to call it yourself.
You may be confused by undefined behavior here. The C++ standard has no rules as to what happens if you use an object after its destructor has been run, as that's undefined behavior, and therefore the implementation can do anything it likes. Typically, compiler designers don't do anything special for undefined behavior, and so what happens is an artifact of what other design decisions were made. (This can cause really weird results sometimes.)
Therefore, once you've run the destructor, the compiler has no further obligation regarding that object. If you don't refer to it again, it doesn't matter. If you do refer to it, that's undefined behavior, and from the Standard's point of view the behavior doesn't matter, and since the Standard says nothing most compiler designers will not worry about what the program does.
In this case, the easiest thing to do is to leave the object untouched, since it isn't holding on to resources, and its storage was allocated as part of starting up the function and will not be reclaimed until the function exits. Therefore, the value of the data member will remain the same. The natural thing for the compiler to do when it reads ob2.day is to access the memory location.
Like any other example of undefined behavior, the results could change under any change in circumstances, but in this case they probably won't. It would be nice if compilers would catch more cases of undefined behavior and issue diagnostics, but it isn't possible for compilers to detect all undefined behavior (some occurs at runtime) and often they don't check for behavior they don't think likely.
I have got a quick question. I have the following code:
class Class1
{
Class1();
~Class1();
void func1();
private:
char* c;
}
void Class1::func1()
{
string s = "something";
this->c = s.c_str();
}
will c store "something" when func1() finishes?
No. It will invoke undefined behavior instead. (if you dereference the pointer, anyway.) Since s is a block-scope object with automatic storage duration, it is destroyed when the function returns, and that renders the pointer returned by .c_str() invalid.
Why not use an std::string member variable instead?
s is a local variable of type std::string in Class::func1. Once func1() finishes, the string s will go out of scope.
Any pointers you have with the address of s stored in them will become dangling pointers.
It will store a dangling pointer that you must not access. It may contain the string "something" or it may not. It doesn't matter, because accessing it is undefined behaviour, and should be avoided completely.
If you want to copy the string do this:
c = strdup( c.c_str() );
And don't forget to free(c) in ~Class1()
Beware that if you call func1 twice, you will leak memory. You probably want to initialise c to NULL in the constructor, and call free(c) before reassigning it in func1.
Surely a better approach is to store a std::string instead of a char*, which manages memory properly for you.
The variable s, will go out of scope once control exits that block, at which point its destructor will be called.
When is an object "out of scope"?
I have a simple C++ code, but I don't know how to use the destructor:
class date {
public:
int day;
date(int m)
{
day =m;
}
~date(){
cout << "I wish you have entered the year \n" << day;
}
};
int main()
{
date ob2(12);
ob2.~date();
cout << ob2.day;
return 0;
}
The question that I have is, what should I write in my destructor code, that after calling the destructor, it will delete the day variable?
Rarely do you ever need to call the destructor explicitly. Instead, the destructor is called when an object is destroyed.
For an object like ob2 that is a local variable, it is destroyed when it goes out of scope:
int main()
{
date ob2(12);
} // ob2.~date() is called here, automatically!
If you dynamically allocate an object using new, its destructor is called when the object is destroyed using delete. If you have a static object, its destructor is called when the program terminates (if the program terminates normally).
Unless you create something dynamically using new, you don't need to do anything explicit to clean it up (so, for example, when ob2 is destroyed, all of its member variables, including day, are destroyed). If you create something dynamically, you need to ensure it gets destroyed when you are done with it; the best practice is to use what is called a "smart pointer" to ensure this cleanup is handled automatically.
You do not need to call the destructor explicitly. This is done automatically at the end of the scope of the object ob2, i.e. at the end of the main function.
Furthermore, since the object has automatic storage, its storage doesn’t have to be deleted. This, too, is done automatically at the end of the function.
Calling destructors manually is almost never needed (only in low-level library code) and deleting memory manually is only needed (and only a valid operation) when the memory was previously acquired using new (when you’re working with pointers).
Since manual memory management is prone to leaks, modern C++ code tries not to use new and delete explicitly at all. When it’s really necessary to use new, then a so-called “smart pointer” is used instead of a regular pointer.
You should not call your destructor explicitly.
When you create your object on the stack (like you did) all you need is:
int main()
{
date ob2(12);
// ob2.day holds 12
return 0; // ob2's destructor will get called here, after which it's memory is freed
}
When you create your object on the heap, you kinda need to delete your class before its destructor is called and memory is freed:
int main()
{
date* ob2 = new date(12);
// ob2->day holds 12
delete ob2; // ob2's destructor will get called here, after which it's memory is freed
return 0; // ob2 is invalid at this point.
}
(Failing to call delete on this last example will result in memory loss.)
Both ways have their advantages and disadvantages. The stack way is VERY fast with allocating the memory the object will occupy and you do not need to explicitly delete it, but the stack has limited space and you cannot move those objects around easily, fast and cleanly.
The heap is the preferred way of doing it, but when it comes to performance it is slow to allocate and you have to deal with pointers. But you have much more flexibility with what you do with your object, it's way faster to work with pointers further and you have more control over the object's lifetime.
Only in very specific circumstances you need to call the destructor directly. By default the destructor will be called by the system when you create a variable of automatic storage and it falls out of scope or when a an object dynamically allocated with new is destroyed with delete.
struct test {
test( int value ) : value( value ) {}
~test() { std::cout << "~test: " << value << std::endl; }
int value;
};
int main()
{
test t(1);
test *d = new t(2);
delete d; // prints: ~test: 2
} // prints: ~test: 1 (t falls out of scope)
For completeness, (this should not be used in general) the syntax to call the destructor is similar to a method. After the destructor is run, the memory is no longer an object of that type (should be handled as raw memory):
int main()
{
test t( 1 );
t.~test(); // prints: ~test: 1
// after this instruction 't' is no longer a 'test' object
new (&t) test(2); // recreate a new test object in place
} // test falls out of scope, prints: ~test: 2
Note: after calling the destructor on t, that memory location is no longer a test, that is the reason for recreation of the object by means of the placement new.
In this case your destructor does not need to delete the day variable.
You only need to call delete on memory that you have allocated with new.
Here's how your code would look if you were using new and delete to trigger invoking the destructor
class date {
public: int* day;
date(int m) {
day = new int;
*day = m;
}
~date(){
delete day;
cout << "now the destructor get's called explicitly";
}
};
int main() {
date *ob2 = new date(12);
delete ob2;
return 0;
}
Even though the destructor seems like something you need to call to get rid of or "destroy" your object when you are done using it, you aren't supposed to use it that way.
The destructor is something that is automatically called when your object goes out of scope, that is, when the computer leaves the "curly braces" that you instantiated your object in. In this case, when you leave main(). You don't want to call it yourself.
You may be confused by undefined behavior here. The C++ standard has no rules as to what happens if you use an object after its destructor has been run, as that's undefined behavior, and therefore the implementation can do anything it likes. Typically, compiler designers don't do anything special for undefined behavior, and so what happens is an artifact of what other design decisions were made. (This can cause really weird results sometimes.)
Therefore, once you've run the destructor, the compiler has no further obligation regarding that object. If you don't refer to it again, it doesn't matter. If you do refer to it, that's undefined behavior, and from the Standard's point of view the behavior doesn't matter, and since the Standard says nothing most compiler designers will not worry about what the program does.
In this case, the easiest thing to do is to leave the object untouched, since it isn't holding on to resources, and its storage was allocated as part of starting up the function and will not be reclaimed until the function exits. Therefore, the value of the data member will remain the same. The natural thing for the compiler to do when it reads ob2.day is to access the memory location.
Like any other example of undefined behavior, the results could change under any change in circumstances, but in this case they probably won't. It would be nice if compilers would catch more cases of undefined behavior and issue diagnostics, but it isn't possible for compilers to detect all undefined behavior (some occurs at runtime) and often they don't check for behavior they don't think likely.
How does C++ ensure that destructors are called for stack assigned objects? What happens to the destructor function (or a pointer to it) when I assign dynamic memory as follows:
class MyClass {
public:
~MyClass()
{
std::cout<<"Destructor called."<<std::endl;
}
MyClass()
{
std::cout<<"Constructor called."<<std::endl;
}
};
....................................................................
//Limit scope for example
{
MyClass instance;
}
The constructor and destructor are both called. What's going on here?
The compiler inserts a call to the destructor for the object at an appropriate position.
You wouldn't wonder why this
{
int i;
}
creates and destroys i automatically, would you? C++ does a lot to allow you to create types that behave just like built-in types. And just like with built-in types, in C++ (other than in, say, Java or C#), this
{
MyClass instance;
}
doesn't just define a reference that might be bound to null or some actual object. It creates an actual object.
Object creation comes in two steps: First (upon entering the scope) the raw memory is provided. Then (when the object definition is encountered) the constructor is called. For built-in types no constructor is called. If you don't initialize a built-in variable, it has a random value. (Actually it's whatever the bit pattern was at the memory provided in step #1.) Object deletion, too, comes in two steps: First, the destructor is called (again, not for built-ins), then the memory is returned to the run-time system.
(Note that providing and deleting memory for stack variables usually is as cheap as incementing/decrementing a register.)
The constructor is called as soon as the variable is created. As for the destructor, the compiler emits code at the end of scope to call the destructor. To get a feel for this, try using a 'goto', or switch/case construct to prematurely exit the scope, and watch the compiler complain.
Yes, both the constructor and destructor are called. And even more important:
{
MyClass instance;
throw "exception";
}
in this example, the destructor is also called. That is why I always prefer to allocate my objects on stack (or at least wrap the dynamic allocations with a stack-allocated guardians).
The constructor is called because you're creating an object. The destructor is called because your cleaning up that object. Remember, in C++, objects declared on the stack are automatically cleaned up when their containing scope goes away.
Well, it did not call the destructor just after constructor.
It calls it when it about to terminate the programme.
int main() {
MyClass obj;
cout<<"testing....1"<<endl;
cout<<"testing....2"<<endl;
return 0;
}
ans:
Constructor called.
testing....1
testing....2
Destructor called.
I have a C++ memory management doubt, that's (obviously) related to references and pointers. Suppose I have a class Class with a method my_method:
OtherClass& Class::my_method( ... ) {
OtherClass* other_object = new OtherClass( ... );
return *other_object;
}
Meanwhile in a nearby piece of code:
{
Class m( ... );
OtherClass n;
n = m.my_method( ... );
}
So, I know that there's a general rule about pointers (~ "anything new-ed, must be delete-d") to avoid memory leaks. But basicly I'm taking a reference to my heap-allocated object, so when n goes out of scope, shouldn't the destructor of OtherClass be called thus freeing the memory previously pointed by other_object?
So in the end the real question is: will this lead to a memory leak?
Thanks.
Yes that will lead to a memory leak.
What you'll do is, in the return statement, dereference the new object you created. The compiler will invoke the assignment operator as part of the returning and copy the CONTENTS of your new object to the object it's assigned to in the calling method.
The new object will be left on the heap, and its pointer cleared from the stack, thus creating a memory leak.
Why not return a pointer and manage it that way?
It's fairly obvious that you want to return a new object to the caller that you do not need to keep any reference to. For this purpose, the simplest thing to do is to return the object by value.
OtherClass Class::my_method( ... ) {
return OtherClass( ... );
}
Then in the calling code you can construct the new object like this.
{
Class m( ... );
OtherClass n( m.mymethod( ... ) );
}
This avoids any worries about returning reference to temporaries or requiring the client to manager deletion of a returned pointer. Note, that this does require your object to be copyable, but it is a legal and commonly implemented optimization for the copy to be avoided when returning by value.
You would only need to consider a shared pointer or similar if you need shared ownership or for the object to have a lifetime outside the scope of the calling function. In this latter case you can leave this decision up to the client and still return by value.
E.g.
{
Class m( ... );
// Trust me I know what I'm doing, I'll delete this object later...
OtherClass* n = new OtherClass( m.mymethod( ... ) );
}
Calling the destructor and freeing the memory are two distinct things in C++.
delete does both call the destructor and free the memory. delete[] calls the destructor for the allocated number of elements, then frees the memory.
When OtherClass goes out of scope, the destructor is called, but the memory is not freed.
As a suggestion, when you feel you have thoroughly understood pointers in C++, look into smart pointers, e.g. boost smart pointers to ease your memory management life in C++. (e.g. see the article here for an introduction)
You have 2 OtherClass objects:
One is n, which is created on the stack, and successfully deleted when goes out of scope.
The other one is the one that you create on the heap, inside my_method. This one is never deleted, and it will lead to memory leak.
If possible you can consider std::auto_ptr or boost/c0x shared_ptr to ease the memory management.
Usually, when a local object gets out of scope, it's memory is freed only because it's allocated on the stack and the stack gets cleaned up automatically. Since your object is allocated on the heap, there's no way it can get automatically freed. The only way to free it is to call delete explicitly.
I think you probably can do this:
Declare another class DummyClass, which contain a public member that is a pointer to OtherClass object. In the constructor of DummyClass, clear the pointer to NULL. In your function, declare an object of type DummyClass, and its member pointer to create another object of type OtherClass. Then in the destructor of DummyClass, check if the pointer is NULL, if it is not, delete it. In this way your object will be cleaned up automatically when DummyClass object goes out of scope.
If you insist on stack-allocation, don't use the new operator in my_method() and pass a reference to n instead, ie:
void Class::my_method( OtherClass& other_object, ... ) {
other_object.init( ... );
}
Then call my_method() like this:
{
Class m( ... );
OtherClass n;
m.my_method( n, ... );
}
For this pattern to work, Class must implement some kind of init() method which allows to correctly initialize objects without calling the constructor.