reference:
- C++ Primer 5th Edition - 13.2 Copy Control and Resource Management
- cppreference - Copy constructors
- cppreference - Copy assignment operator
You need to be very careful when you delete a pointer. If you delete a pointer which does't point to a legal allocted memory, the programe will be crashed.
main.cpp
#include "parent.h"
#include "hasstr.h"
#define LOG(X) std::cout<<"[file:"<<__FILE__<<" line:"<<__LINE__<<"]-["<<__FUNCTION__<< "]"<< "\n"<<X<<"\n\n";
int main(int argc, char *argv[])
{
std::cout << "---Start initialize \"A\" to object1---\n";
HasStr hasStr1("A");
std::cout << "------Copy object1 to object2------\n";
HasStr hasStr2(hasStr1);
std::cout << "------Start initialize \"B\" to object3------\n";
HasStr hasStr3("B");
std::cout << "------Copy object3 to object4------\n";
HasStr hasStr4(hasStr3);
std::cout << "------Assign object2 to object4------\n";
hasStr4 = hasStr2;
std::cout << "------Assign object1 to object3------\n";
hasStr3 = hasStr1;
std::cout << "------Main Over.------\n";
}
hasstr.h
#ifndef HASSTR_H
#define HASSTR_H
#include <iostream>
#define LOG(X) std::cout<<"[file:"<<__FILE__<<" line:"<<__LINE__<<"]-["<<__FUNCTION__<< "]"<< "\n"<<X<<"\n\n";
class HasStr
{
public:
HasStr()=default;
HasStr(const std::string &s = std::string());
HasStr(HasStr &);
HasStr& operator=(const HasStr&);
~HasStr();
private:
std::string *ps;
std::size_t *usecount;
};
#endif // HASSTR_H
hasstr.cpp
#include "hasstr.h"
HasStr::HasStr(const std::string &s):
ps(new std::string(s)),usecount(new std::size_t(1))
{
LOG("HasStr constructor,create std::string pointer ps by new")
};
HasStr::HasStr(HasStr& h):ps(h.ps),usecount(h.usecount)
{
LOG("HasStr copy constructor")
(*usecount)++;
}
HasStr& HasStr::operator=(const HasStr& rhs)
{
LOG("HasStr copy assignment constructor");
++*rhs.usecount;
if(--*usecount == 0)
{
LOG(*ps << "'s usecount reduced to zero, delete pointer ps and usecount.");
delete ps;
delete usecount;
}
ps = rhs.ps;
usecount = rhs.usecount;
return *this;
}
HasStr::~HasStr()
{
LOG("HasStr deconstructor,"<<*ps<<"'s usecount is "<<*usecount)
if(--(*usecount) == 0)
{
LOG(*ps << "'s usecount reduced to zero, delete pointer ps and usecount.");
delete ps;
delete usecount;
}
}
output:
---Start initialize "A" to object1---
[file:..\CppLearningDemo\hasstr.cpp line:6]-[HasStr::HasStr]
HasStr constructor,create std::string pointer ps by new
------Copy object1 to object2------
[file:..\CppLearningDemo\hasstr.cpp line:11]-[HasStr::HasStr]
HasStr copy constructor
------Start initialize "B" to object3------
[file:..\CppLearningDemo\hasstr.cpp line:6]-[HasStr::HasStr]
HasStr constructor,create std::string pointer ps by new
------Copy object3 to object4------
[file:..\CppLearningDemo\hasstr.cpp line:11]-[HasStr::HasStr]
HasStr copy constructor
------Assign object2 to object4------
[file:..\CppLearningDemo\hasstr.cpp line:17]-[HasStr::operator =]
HasStr copy assignment constructor
------Assign object1 to object3------
[file:..\CppLearningDemo\hasstr.cpp line:17]-[HasStr::operator =]
HasStr copy assignment constructor
[file:..\CppLearningDemo\hasstr.cpp line:21]-[HasStr::operator =]
B's usecount reduced to zero, delete pointer ps and usecount.
------Main Over.------
[file:..\CppLearningDemo\hasstr.cpp line:32]-[HasStr::~HasStr]
HasStr deconstructor,A's usecount is 4
[file:..\CppLearningDemo\hasstr.cpp line:32]-[HasStr::~HasStr]
HasStr deconstructor,A's usecount is 3
[file:..\CppLearningDemo\hasstr.cpp line:32]-[HasStr::~HasStr]
HasStr deconstructor,A's usecount is 2
[file:..\CppLearningDemo\hasstr.cpp line:32]-[HasStr::~HasStr]
HasStr deconstructor,A's usecount is 1
[file:..\CppLearningDemo\hasstr.cpp line:35]-[HasStr::~HasStr]
A's usecount reduced to zero, delete pointer ps and usecount.