Example of rule of three. Must include copy ctor, destructor and assignment operator for classes that use dynamic memory on the heap.
#include <iostream>
using namespace std;
class mystring{
private:
char* _s;
size_t _len;
friend ostream& operator<<(ostream &, const mystring& );
public:
mystring();
~mystring();
mystring(const char*);
mystring(const mystring&); //copy ctor
size_t length() const;
mystring& operator=(const mystring&);
mystring& operator=(const char*);
};
//helper functions
//=======================
ostream& operator<<(ostream &o, const mystring &ms){ //friend
for (size_t x=0; x<ms._len ; x++)
o << ms._s[x];
return o;
}
size_t mystrlen(const char* cstr){
size_t x=0;
while (cstr[x] != '\0')
x++;
return x;
}
//========================
//member functions
//========================
mystring::mystring(){
_s= nullptr;
_len=0;
}
mystring::~mystring(){
delete[] _s;
}
mystring::mystring(const char* st ){ //overloaded ctor
size_t size = mystrlen(st); //helper function
_s= new char[size];
for (size_t x=0; x<size ; x++)
_s[x]=st[x];
_len=size;
}
mystring::mystring(const mystring& ms){ //copy ctor
_s = new char[ ms.length() ];
for (size_t x=0; x<ms.length(); x++)
_s[x] = ms._s[x];
_len=ms.length();
}
size_t mystring::length() const{
return _len;
}
mystring& mystring::operator=(const mystring &ms){
delete[] _s;
_s = new char[ ms.length() ];
for (size_t x=0; x<ms.length(); x++)
_s[x] = ms._s[x];
_len=ms.length();
return *this;
}
mystring& mystring::operator=(const char* st){
delete[] _s;
size_t size = mystrlen(st);
_s= new char[size];
for (size_t x=0; x<size ; x++)
_s[x] = st[x];
_len=size;
return *this;
}
//==============================================
mystring foo(mystring b){
mystring d;
d=b;
return d; //copy ctor called
} //d is deleted
int main(){
mystring b;
b="world";
cout<<b<<endl;
if (1)
{
mystring a("hello");
b=a; //operator= required
} // a gets destroyed
cout<<b<<endl;
cout<<foo(b)<<endl; //copy ctor required or double free
return 0;
}