Meaning of "~" (tilde) symbol in C++? - c++

// AirlineTicket.h
class AirlineTicket
{
public:
AirlineTicket();
~AirlineTicket();
int getNumberOfMiles();
private:
int mNumberOfMiles;
};
I want now what is the meaning of ~AirlineTicket(); in this code?
I don't know the meaning of ~ (tilde).

It is the destructor.
It gets called when you destroy (reaching end of scope, or calling delete to a pointer to) the instance of the object.

In the context you're using it, it defines a destructor.
In other context such as the following one, it's also called bitwise negation (complement):
int a = ~100;
int b = ~a;
Output: (ideone)
-101
100

~ signs that it is a destructor and when ever the object goes out of scope, corresponding destructor is called.
When the destructor is called ?
Taking an example -
#include <iostream>
class foo
{
public:
void checkDestructorCall() ;
~foo();
};
void foo::checkDestructorCall()
{
foo objOne; // objOne goes out of scope because of being a locally created object upon return of checkDestructorCall
}
foo:: ~foo()
{
std::cout << "Destructor called \t" << this << "\n";
}
int main()
{
foo obj; // obj goes of scope upon return of main
obj.checkDestructorCall();
return 0;
}
Results on my system:
Destructor called 0xbfec7942
Destructor called 0xbfec7943
This example just serves to indicate when a destructor is called. But destructor is written only when the class manages resources.
When class manages resources?
#include <iostream>
class foo
{
int *ptr;
public:
foo() ; // Constructor
~foo() ;
};
foo:: foo()
{
ptr = new int ; // ptr is managing resources.
// This assignment can be modified to take place in initializer lists too.
}
foo:: ~foo()
{
std::cout << "Destructor called \t" << this << "\n";
delete ptr ; // Returning back the resources acquired from the free store.
// If this isn't done, program gives memory leaks.
}
int main()
{
foo *obj = new foo;
// obj is pointing to resources acquired from free store. Or the object it is pointing to lies on heap. So, we need to explicitly call delete on the pointer object.
delete obj ; // Calls the ~foo
return 0;
}
Results on my system:
Destructor called 0x9b68008
And in the program, you posted I don't see a need to write destructor. Hope it helps !

It's the class destructor. You might want to pick up an introductory text on C++ development, as destructors are a fundamental concept in OOP. There is a good reference site here, and the C++ FAQ is another good resource.

~AirlineTicket(); is the destructor for the class AirlineTicket
see this link for further reference
The destructor is called when you delete the object of that class, to free any memory allocated or resources being used by the object.

~ introduces a destructor. It's used because (a) it was available, ad (b) ~ is one (of several) mathematical notation for "not".

This indicates destructor of class.
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr380.htm

Related

C++ destructor with return

In C++ if we define a class destructor as:
~Foo(){
return;
}
upon calling this destructor will the object of Foo be destroyed or does
explicitly returning from the destructor mean that we don't ever want to destroy it.
I want to make it so that a certain object is destroyed only through another objects destructor i.e. only when the other object is ready to be destroyed.
Example:
class Class1{
...
Class2* myClass2;
...
};
Class1::~Class1(){
myClass2->status = FINISHED;
delete myClass2;
}
Class2::~Class2(){
if (status != FINISHED) return;
}
I searched online and couldn't seem to find an answer to my question.
I've also tried figuring it out myself by going through some code step by step with a debugger but can't get a conclusive result.
No, you can't prevent the object from being destroyed by return statement, it just means the execution of the dtor's body will end at that point. After that it still will be destroyed (including its members and bases), and the memory still will be deallocated.
You migth throw exception.
Class2::~Class2() noexcept(false) {
if (status != FINISHED) throw some_exception();
}
Class1::~Class1() {
myClass2->status = FINISHED;
try {
delete myClass2;
} catch (some_exception& e) {
// what should we do now?
}
}
Note it's a terrible idea indeed. You'd better to reconsider the design, I'm sure there must be a better one. Throwing exception won't stop the destruction of its bases and members, just make it possible to get the process result of Class2's dtor. And what could be done with it is still not clear.
~Foo(){
return;
}
means exactly the same as:
~Foo() {}
It is similar to a void function; reaching the end without a return; statement is the same as having return; at the end.
The destructor contains actions that are performed when the process of destroying a Foo has already begun. It's not possible to abort a destruction process without aborting the entire program.
[D]oes explicitly returning from the destructor mean that we don't ever want to destroy it?
No. An early return (via return; or throw ...) only means the rest of the body of the destructor is not executed. The base and members are still destroyed and their destructors still run, see [except.ctor]/3.
For an object of class type of any storage duration whose initialization or destruction is terminated by an exception, the destructor is invoked for each of the object's fully constructed subobjects...
See below for code samples of this behaviour.
I want to make it so that a certain object is destroyed only through another objects destructor i.e. only when the other object is ready to be destroyed.
It sounds like the question is rooted in the issue of ownership. Deleting the "owned" object only once the parent is destroyed in a very common idiom and achieved with one of (but not limited to);
Composition, it is an automatic member variable (i.e. "stack based")
A std::unique_ptr<> to express exclusive ownership of the dynamic object
A std::shared_ptr<> to express shared ownership of a dynamic object
Given the code example in the OP, the std::unique_ptr<> may be a suitable alternative;
class Class1 {
// ...
std::unique_ptr<Class2> myClass2;
// ...
};
Class1::~Class1() {
myClass2->status = FINISHED;
// do not delete, the deleter will run automatically
// delete myClass2;
}
Class2::~Class2() {
//if (status != FINISHED)
// return;
// We are finished, we are being deleted.
}
I note the if condition check in the example code. It hints at the state being tied to the ownership and lifetime. They are not all the same thing; sure, you can tie the object reaching a certain state to it's "logical" lifetime (i.e. run some cleanup code), but I would avoid the direct link to the ownership of the object. It may be a better idea to reconsider some of the semantics involved here, or allow the "natural" construction and destruction to dictate the object begin and end states.
Side note; if you have to check for some state in the destructor (or assert some end condition), one alternative to the throw is to call std::terminate (with some logging) if that condition is not met. This approach is similar to the standard behavior and result when an exception is thrown when unwinding the stack as a result of an already thrown exception. This is also the standard behavior when a std::thread exits with an unhandled exception.
[D]oes explicitly returning from the destructor mean that we don't ever want to destroy it?
No (see above). The following code demonstrates this behaviour; linked here and a dynamic version. The noexcept(false) is needed to avoid std::terminate() being called.
#include <iostream>
using namespace std;
struct NoisyBase {
NoisyBase() { cout << __func__ << endl; }
~NoisyBase() { cout << __func__ << endl; }
NoisyBase(NoisyBase const&) { cout << __func__ << endl; }
NoisyBase& operator=(NoisyBase const&) { cout << __func__ << endl; return *this; }
};
struct NoisyMember {
NoisyMember() { cout << __func__ << endl; }
~NoisyMember() { cout << __func__ << endl; }
NoisyMember(NoisyMember const&) { cout << __func__ << endl; }
NoisyMember& operator=(NoisyMember const&) { cout << __func__ << endl; return *this; }
};
struct Thrower : NoisyBase {
Thrower() { cout << __func__ << std::endl; }
~Thrower () noexcept(false) {
cout << "before throw" << endl;
throw 42;
cout << "after throw" << endl;
}
NoisyMember m_;
};
struct Returner : NoisyBase {
Returner() { cout << __func__ << std::endl; }
~Returner () noexcept(false) {
cout << "before return" << endl;
return;
cout << "after return" << endl;
}
NoisyMember m_;
};
int main()
{
try {
Thrower t;
}
catch (int& e) {
cout << "catch... " << e << endl;
}
{
Returner r;
}
}
Has the following output;
NoisyBase
NoisyMember
Thrower
before throw
~NoisyMember
~NoisyBase
catch... 42
NoisyBase
NoisyMember
Returner
before return
~NoisyMember
~NoisyBase
According to the C++ Standard (12.4 Destructors)
8 After executing the body of the destructor and destroying any
automatic objects allocated within the body, a destructor for class X
calls the destructors for X’s direct non-variant non-static data
members, the destructors for X’s direct base classes and, if X is the
type of the most derived class (12.6.2), its destructor calls the
destructors for X’s virtual base classes. All destructors are called
as if they were referenced with a qualified name, that is, ignoring
any possible virtual overriding destructors in more derived classes.
Bases and members are destroyed in the reverse order of the completion
of their constructor (see 12.6.2). A return statement (6.6.3) in a
destructor might not directly return to the caller; before
transferring control to the caller, the destructors for the members
and bases are called. Destructors for elements of an array are called
in reverse order of their construction (see 12.6).
So a returning statement does not prevent the object for which the destructor is called to be destroyed.
does explicitly returning from the destructor mean that we don't ever want to destroy it.
No.
The destructor is a function so you can use the return keyword inside of it but that won't prevent the destruction of the object, once you are inside the destructor you are already destroying your object so any logic that wants to prevent that will have to occur before.
For some reason i intuitively think your design problem can be solved with a shared_ptr and maybe a custom deleter, but that would require more info on the said problem.
All stack-based objects inside will get destructed, no matter how soon you return from the destructor. If you miss to delete dynamically allocated objects, then there would be intentional memory leak.
This is the whole idea how move-constructors would work. The move CTOR would simply take original object's memory. The destructor of original object simply wont/cant call delete.
No. return just means exit the method, it doesn't stop the destruction of the object.
Also, why would you want to? If the object is allocated on the stack and you somehow managed to stop destruction then the object would live on a reclaimed part of the stack that will probably be overwritten by the next function call, which may write all over your objects memory and create undefined behavior.
Likewise, if the object is allocated on the heap and you managed to prevent destruction you'd have a memory leak as the code calling delete would assume that it didn't need to hold on to a pointer to the object whilst it's actually still there and taking up memory that nobody is referencing.
Of course not. Explicit call of 'return' ist 100% equivalent to implicit returning after execution of the destructor.
You can make a new method to make the object "commit suicide" and keep the destructor empty, so something like this will do the job you would like to do:
Class1::~Class1()
{
myClass2->status = FINISHED;
myClass2->DeleteMe();
}
void Class2::DeleteMe()
{
if (status == FINISHED)
{
delete this;
}
}
Class2::~Class2()
{
}
So, as all the others pointed out, return is not a solution.
The first thing I would add is that you shouldn't usually worry about this. Unless your professor explicitly asked.
It would be very odd if you could't trust the external class to only delete your class at the right time, and I figure no one else is seeing it.
If the pointer is passed around, the pointer would very probably be shared_ptr/weak_ptr, and let it destroy your class at the right moment.
But, hey, it's good to wonder how we would solve an odd problem if it ever arose, if we learn something (and don't waste time while on a deadline!)
So what for a solution? If you can at least trust the destructor of Class1 not to destroy your object too early, then you can just declare the destructor of Class2 as private, and then declare the destructor of Class1 as friend of Class2, like this:
class Class2;
class Class1 {
Class2* myClass2;
public:
~Class1();
};
class Class2 {
private:
~Class2();
friend Class1::~Class1();
};
Class1::~Class1() {
delete myClass2;
}
Class2::~Class2() {
}
As a bonus, you don't need the 'status' flag; which is good -if someone wanted this bad to screw with you, why wouldn't set the status flag to FINISHED anywhere else, and then call delete?
This way, you have actual guarantee that the object can be destroyed nowhere else than in the destructor of Class1.
Of course, the destructor of Class1 gets access to all private members of Class2. It might not matter -after all, Class2 is about to be destroyed anyway! But if it does, we can conjure even more convoluted ways to work around it; why not. For instance:
class Class2;
class Class1 {
private:
int status;
Class2* myClass2;
public:
~Class1();
};
class Class2Hidden {
private:
//Class2 private members
protected:
~Class2Hidden();
public:
//Class2 public members
};
class Class2 : public Class2Hidden {
protected:
~Class2();
friend Class1::~Class1();
};
Class1::~Class1() {
delete myClass2;
}
Class2Hidden::~Class2Hidden() {
}
Class2::~Class2() {
}
This way the public members will still be available in the derived class, but the private members will actually be private. ~Class1 will only get access to the private and protected members of Class2, and the protected members of Class2Hidden; which in this case is only the destructors.
If you need to keep a protected member of Class2 protected from the destructor of Class1... there are ways, but it really depends on what you are doing.
Good luck!
For this case you could use a class-specific overload of the delete operator.
So for you Class2 you could something like this
class Class2
{
static void operator delete(void* ptr, std::size_t sz)
{
std::cout << "custom delete for size " << sz << '\n';
if(finished)
::operator delete(ptr);
}
bool Finished;
}
Then if you set the finished to true before the delete, the actual deletion will be called.
Note that i haven't tested it, i just modified the code that i've found here
http://en.cppreference.com/w/cpp/memory/new/operator_delete
Class1::~Class1()
{
class2->Finished = true;
delete class2;
}

When is C++ destructor called on an object in heap?

Suppose a class and its usage
#include <vector>
class B
{
public:
B() {temp = 0;}; // implemented
~B() {} ; // implmented
private :
int temp;
// it holds a std::bitset , a std::vector.. It is quite large in size.
};
class A
{
private:
std::vector<B*> * _data ;
public:
A()
{
_data = new std::vector<B*>(0);
}
~A()
{
for(unsigned int idx_ = 0; idx_ < _data->size(); ++idx_)
delete _data->at(idx_);
delete _data ;
}
void addB()
{
B * temp = new B();
_data->push_back(temp);
}
}
int main()
{
A temp;
temp.addB();
// Do something
}
My question is does this code leak memory ? Also suppose another usage
int main()
{
A * temp = new A();
temp->addB();
delete temp ; // 1
}
Is 1 here required ? If I have a pointer to the heap and the pointer goes out of scope is the destructor called on the element in heap. I just want to be sure about this point.
Thank you !
To make it easier to associate when a destructor will be called and when it wont be, use this rule of thumb: When the memory for an object is being reclaimed, then the object's destructor is called (and the memory is reclaimed right after that).
Your first example does not leak any memory.
Here is why... You essentially created 2 objects.
A and B.
A was on the stack. The memory for object A was created implicitly on the stack.
B was created on the heap explicitly by your code.
When main() returned every Object on the stack is destroyed. i.e the memory that was being used to hold the members of the object on the stack (in this case object A) is being reclaimed implicitly. Since the object (A) is actually being destroyed and its memory being reclaimed, the destructor for A gets called.
Within A's destructor you are explicitly telling the runtime to reclaim all the memory what was explicitly allocated by your code (i.e when you call delete). Thus the memory for object B is being reclaimed too.
Thus there was no leak.
In the 2nd example, you again create 2 objects A and B.
Here, the memory for both objects resides in the heap. This was allocated explicitly by your code using the new operator.
In this case, your code never reclaims the memory allocated for A. i.e delete is never called for A.
The stack for main() only contains the memory for a pointer to A. The main() stack itself does not contain the memory for A. So when main() returns, all that is being destroyed is the memory that was allocated for the pointer to A, and not A itself.
Since the memory for A was never reclaimed, it was never "destroyed". Thus its destructor was never called and correspondingly "B" was never destroyed either.
No, destructor is not implicitly called. you have to delete temp, at which time it's destructor is called. It could be argued that since it's main that's returning in your example, the process is going to exit and memory will be reclaimed by OS, but in general, each new needs a delete.
The rule of thumb is if you've used new to create something then you have to use delete to destroy it. Pointers are all about manual memory management (they are heritage from the C language) or, as Scott Meyers once called them, "running with scissors". References are a C++ thing (or you can also check out smart pointers like std::shared_ptr).
UPDATE
I thought it would be useful to show an example with std::shared_ptr. It has dumb pointer semantics, but its destructor -since it actually has one- calls pointed object's destructor.
#include <memory>
#include <iostream>
#include <string>
#include <type_traits>
using namespace std;
struct Simple {
std::string txt;
Simple(const std::string& str) : txt(str) {}
Simple(){}
~Simple() { cout << "Destroyed " << txt << endl; }
};
template<class U> using SPtr = shared_ptr<U>;
template<class V> using PtrToSimple = typename conditional<is_same<SPtr<Simple>, V>::value,SPtr<Simple>,Simple*>::type;
template<class T>
void modify(PtrToSimple<T> pt) {
pt->txt.append("_modified");
// equivalent to (*pt).txt.append("_modified");
}
int main() {
auto shared = shared_ptr<Simple>(new Simple("shared_ptr_obj"));
modify<decltype(shared)>(shared);
cout << shared->txt << endl;
auto dumb = new Simple("dumb_ptr_obj");
modify<decltype(dumb)>(dumb);
cout << dumb->txt << endl;
// The object pointed by 'shared'
// will be automatically deleted.
// dumb's object won't
return 0;
}
prints
shared_ptr_obj_modified
dumb_ptr_obj_modified
Destroyed shared_ptr_obj_modified

Does a destructor automatically deallocates heap memory for member variables?

I have a few doubts related to destructor.
class cls
{
char *ch;
public:
cls(const char* _ch)
{
cout<<"\nconstructor called";
ch = new char[strlen(_ch)];
strcpy(ch,_ch);
}
~cls()
{
//will this destructor automatically delete char array ch on heap?
//delete[] ch; including this is throwing heap corruption error
}
void operator delete(void* ptr)
{
cout<<"\noperator delete called";
free(ptr);
}
};
int main()
{
cls* cs = new cls("hello!");
delete(cs);
getchar();
}
Also, as a destructor is automatically called upon delete why do we need an explicit delete when all the logic can be written in destructor?
I am super confused regarding operator delete and destructor and couldn't make out their specific usage. An elaborate description would be very helpful.
EDIT:
My understanding based on the answers:
For this particular case, a default destructor will corrupt the char pointer so we need to explicitly delete the char array first other wise it will result in memory leak. Please correct me if I am wrong.
Well, a default destructor deallocates memory that is used by member variables (i.e. the member pointer ch itself ceases to exist), but it does not automatically deallocate any memory that is referenced by member pointers. So there is a memory leak in your example.
delete is not a function (though you can overload it); and yes, it is good practice that the logic for the deallocation be written in the destructor. But it is incorrect to assume that the deallocation will be automatically performed by the destructor. The thing is that the destructor will be called at the end of the object's lifetime, but what it does it dependent upon the code you write for it. That is, you should call delete[] on ch inside the destructor:
~cls()
{
delete[] ch;
ch = nullptr;
}
Moreover, I believe the heap corruption error is coming from that fact that you did not leave enough room in the initialization of ch for the null byte \0. You should also be using the the member-initializer list. Change your constructor to this:
cls(const char* _ch) : ch(new char[1+strlen(_ch)])
{
std::cout << "\nconstructor called";
std::strcpy(ch, _ch);
}
There are many improvements that can be made to your code. Namely, using std::string and following the Rule Of Three. Your code also doesn't need a operator delete() overload. cs should be stack allocated:
#include <iostream>
#include <string>
class cls
{
std::string ch;
public:
cls() { std::cout << "default constructor called\n"; }
cls(std::string _ch) : ch(_ch)
{
std::cout << "constructor called\n";
}
cls(cls const& other) : ch(other.ch)
{
std::cout << "copy-constructor called\n";
}
~cls() { std::cout << "destructor called\n"; }
};
int main()
{
cls cs("hello!");
std::cin.get();
} // <-- destructor gets called automatically for cs
No, the destructor won't magically delete the memory pointed to by ch for you. If you called new (you did in the constructor) then you must also call delete at some appropriate time.
A destructor executes when an object is being destroyed. This can be when an automatic object (that is something allocated on the stack) is about to go out of scope, or when you explicitly delete an object allocated with new.
Generally, think of new as a way of getting memory allocated, a constructor as a way of taking that memory and making it into an object, a destructor as taking an object and destroying it, leaving behind a chunk of memory and delete as taking that chunk of memory and deallocating it.
As a convenience for you, when you call new the compiler will call the constructor for you after it allocates the memory you requested and when you call delete the compiler will automatically invoke the destructor for you.
You are getting heap corruption errors because you have a buffer oveflow: you are not allocating space for the null terminating byte that strcpy appends.
Remember a C string is a sequence of bytes followed by a null byte. This means that a string of length 5 actually requires 6 bytes to store.
Also remember that you can and should use std::string instead of C style arrays to save yourself the trouble and avoid having to write error-prone code when there's a very robust and full-featured implementation already available for your use.
With the notable exception of homework/learning exercises, there is hardly a situation where you should implement C style strings directly instead of using std::string.
The same (albeit a little less strict) goes for dynamic arrays in general. Use std::vector instead.
There is no use in override the delete Operator for a specific class. That's what the global delete Operator is for.
What you should do is a delete[] on ch in the destructor. This has to be done explicitly, as the delete Operator only deallocates the memory directly allocated to store the class' instance. As you are allocating further Memory in the constructor you have to free it upon destruction.
As a rule of thumb you can assume that con- and destructor need to be coded symmetricly. For every new in the constructor, has to be a delete in de destructor.
Oh and by the way: You must not mix C++ allocators (new/delete) with C allocators (malloc/free). What you allocate in C++, you have to free in C++ and vice versa.
C++ memory magnament is based on RAII. That means that destructors are called when the lifetime of a variable ends.
For example:
class Foo
{
public:
Foo() { cout << "Constructor!!!" << endl; }
~ Foo() { cout << "Destructor!!!" << endl; }
};
int main()
{
Foo my_foo_instance;
}
Prints:
Constructor!!!
Destructor!!!
Because the constructor is called in the initiallization of my_foo_instance (At the declaration), and the destructor is called when the lifetime of my_foo_instanceends (That is, at the end of main() ).
Also, this rules works for any context, including class attributes:
class Foo1
{
public:
Foo1() { cout << "Foo1 constructor!!!" << endl; }
~ Foo1() { cout << "Foo1 destructor!!!" << endl; }
};
class Foo2
{
private:
Foo1 foo1_attribute;
public:
Foo2() { cout << "Foo2 constructor!!!" << endl; }
~ Foo2() { cout << "Foo2 destructor!!!" << endl; }
};
int main()
{
Foo2 my_foo2_instance;
}
Prints:
Foo1 constructor!!!
Foo2 constructor!!!
Foo2 destructor!!!
Foo1 destructor!!!
The trace of the program is:
Main starts
Initiallization of my_foo2_instance: Call to Foo2 constructor
First of all, Foo2 initializes its attributes: Call to Foo1 constructor
Foo1 has no attributes, so Foo1 executes its constructor body: cout << "Foo1 constructor" << endl;
After attributes initiallization, Foo2 executes its constructor body: cout << "Foo2 constructor" << endl;
End of main scope, so end of my_foo2_instance lifetime: Call to Foo2 destructor
Foo2 destructor executes its body: cout << "Foo2 destructor" << endl;
After the destructor, the lifetime of the attributes of Foo2 ends. So: Call to Foo1 destructor
Foo1 destructor executes its body: cout << "Foo1 destructor" << endl;
After the destructor, the lifetime of the attributes of Foo1 ends. But Foo1 has no attributes.
But what you forget is that a pointer its a basic type, so it has no destructor. To destroy the object pointed by the pointer (Thats is, finallize the life of the pointee object), use use delete operator in destructor body.
Destructor never deallocates anything on its own accord. Destructor will only implicitly call destructors for class subobjects and execute whatever code you put into the destructor's body. Since in your case the subobject ch is of raw pointer type, it has no destructor. So nothing will be done in your case. Since it is you who allocated the memory, it is you who's responsible for deallocating it. In short, yes, you do need that delete[] ch in your destructor.
If you want that memory deallocated automatically, use a smart pointer class instead of a raw pointer. In that case the destructor of your class will automatically call the destructor of the smart pointer subobject, which will deallocate memory for you. In your specific example an even better idea would be to use std::string to store the string inside the class object.
The heap corription in your case is caused by the fact that you allocate insufficient memory for your string, which leads to an out-of-bounds write in strcpy. It should be
ch = new char[strlen(_ch) + 1];
strcpy(ch,_ch);
The extra space is needed for the terminating zero character.
My take:
1) The short answer is no.
2) As for "why not", consider the following example:
cls create()
{
cls Foo("hello"); // This allocates storage for "ch"
return Foo;
} // Return variable is by value, so Foo is shollow-copied (pointer "ch" is copied).
// Foo goes out of scope at end of function, so it is destroyed.
// Do you want member variable "ch" of Foo to be deallocated? Certainly not!
// Because this would affect your returned instance as well!
Recommendations:
If you want to see whether your code leaks storage, you may use an excellent tool valgrind, http://valgrind.org/
As for what to read to understand this topic better, I would recommend the standard C++ literature, plus have a look at smart pointers, e.g. unique pointer
http://www.cplusplus.com/reference/memory/unique_ptr/
which will help you understand the topic and everything will be put to place.

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?
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.
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()"
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.
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.
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.
The _segmentObject is allocated automatically on the stack.
The object destructor will be called automatically when the variable gets out of scope.
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.

Why is the destructor not called for the returned object from the function?

I was thinking that when a function returns an object on the stack to the calling function, the calling function gets a copy of the original object but the original object's destructor is called as soon as the stack unwinds. But in the following program, the destructor is getting called only once. I expected it to be called twice.
#include <iostream>
class MyClass
{
public:
~MyClass() { std::cout << "destructor of MyClass" << std::endl; }
};
MyClass getMyClass()
{
MyClass obj = MyClass();
return obj; // dtor call for obj here?
}
int main()
{
MyClass myobj = getMyClass();
return 0; // Another dtor call for myobj.
}
But "destructor of MyClass" is getting printed only once. Is my assumption wrong or is there something else going on here?
This is a special case where the compiler is allowed to optimize out the copy: this is called named return value optimization (NRVO). Basically, the compiler allocates memory for the return object on the call site and lets the function fill in that memory directly instead of creating the object at the called site and copying it back. Modern compilers do this routinely whenever possible (there are some situations where this isn't easy since there are several return paths in the function that return different instances).