C++ Practice 002:Defining classes that act like pointers

134 阅读1分钟

reference:

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.