When exactly is destructor being called? Initially, I thought that destructor were supposed to be called when we use the:
delete [] str;
Then, when I came accross the "move assignment" topic, I notice that the destructor is called directly after I NULL my rhs.str
in my move assignment
method.
main.cpp
int main() {
Mystring a{"Hello"}; // Overloaded constructor
a = Mystring{"Hola"}; // Overloaded constructor then move assignment
// cout << a.get_str() << endl;
a = "Bonjour"; // Overloaded constructor then move assignment
return 0;
}
Mystring.h
#ifndef _MYSTRING_H_
#define _MYSTRING_H_
class Mystring
{
private:
char *str; // pointer to a char[] that holds a C-style string
public:
Mystring(); // No-args constructor
Mystring(const char *s); // Overloaded constructor
Mystring(const Mystring &source); // Copy constructor
Mystring(Mystring &&source); // Move constructor
~Mystring(); // Destructor
Mystring &operator=(const Mystring &rhs); // Copy assignment
Mystring &operator=(Mystring &&rhs); // Move assignment
void display() const;
int get_length() const; // getters
const char *get_str() const;
};
#endif // _MYSTRING_H_
Mystring.cpp
// No-args constructor
Mystring::Mystring()
: str{nullptr} {
str = new char[1];
*str = '\0';
}
// Overloaded constructor
Mystring::Mystring(const char *s)
: str {nullptr} {
if (s==nullptr) {
str = new char[1];
*str = '\0';
} else {
str = new char[strlen(s)+1];
strcpy(str, s);
}
}
// Copy constructor
Mystring::Mystring(const Mystring &source)
: str{nullptr} {
str = new char[strlen(source.str)+ 1];
strcpy(str, source.str);
std::cout << "Copy constructor used" << std::endl;
}
// Move constructor
Mystring::Mystring(Mystring &&source)
: str(source.str)
{
source.str = nullptr;
std::cout << "Move constructor used" << std::endl;
}
// Destructor
Mystring::~Mystring()
{
if (str == nullptr) {
std::cout << "Calling destructor for Mystring : nullptr" << std::endl;
} else {
std::cout << "Calling destructor for Mystring : " << str << std::endl;
}
delete [] str;
}
// Copy assignment
Mystring &Mystring::operator=(const Mystring &rhs) {
std::cout << "Using copy assignment" << std::endl;
if (this == &rhs)
return *this;
delete [] str;
str = new char[strlen(rhs.str) + 1];
strcpy(str, rhs.str);
return *this;
}
//Move assignment
Mystring &Mystring::operator=(Mystring &&rhs) {
std::cout << "Using move assignment" << std::endl;
if (this == &rhs)
return *this;
delete [] this->str;
this->str = rhs.str;
rhs.str = nullptr;
return *this;
}
The output is as follow:
Using move assignment
Calling destructor for Mystring : nullptr
Using move assignment
Calling destructor for Mystring : nullptr
Calling destructor for Mystring : Bonjour
I have tried debugging but I just have no idea why it went into the Destructor method when I did not explicitly called the
delete [] str // or maybe
delete [] rhs.str
As you can see in the output, my r-value is deleted after every move assignment. I thought that every object should at least be deleted before the return 0;