1. What is a pointer only?
(1) Use it like a pointer
(2) It will release resources by itself
2. Manual release of resources
Before there were no smart pointers, we all used manual release methods.
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std; //smart pointer //1. Use it like a pointer //2. Will release resources by itself class CStudent { public: CStudent() { } void test() { cout << "CStudent" << endl; } private: char* m_pszBuf; int m_nSex; }; int main(int argc, char* argv[]) { //Object is constructed with no arguments CStudent* pStu = new CStudent(); //release manually if (pStu!=nullptr) { delete pStu; pStu = nullptr; } return 0; }
3. Use class construction and destructor to achieve resource management
Create a class and use the mechanism of the class's construction and destruction (into and out of scopes are automatically called by the compiler) to solve the problem of automatic resource release.
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std; //smart pointer //1. Use it like a pointer //2. Will release resources by itself class CStudent { public: CStudent() { } void test() { cout << "CStudent" << endl; } private: char* m_pszBuf; int m_nSex; }; //Create a class that utilizes the mechanism of the class's construction and destructor (in and out of scope automatically invoked by the compiler) //To solve the problem of automatic resource release //Smart pointer prototype for managing resources class CSmartPtr { public: //It must be a heap object, because it uses the construction and destructor to manage resources CSmartPtr(CStudent* pObj) { m_pObj = pObj; } ~CSmartPtr() { if (m_pObj != nullptr) { delete m_pObj; } } private: CStudent* m_pObj;//Put resources into smart pointer classes and manage them }; int main(int argc, char* argv[]) { CSmartPtr sp(new CStudent()); return 0; }
4. Need to find a way to make the object act like a pointer
Earlier, we learned how to use reference counting and copy-on-write, which are essential for understanding smart pointers. However, in actual writing code, we actually prefer to let programmers have no perception of resource management. That is to say, it is best for programmers to only need to consider when to apply for resources, when to release and internal resources of resources. How to count and other issues are all handed over to the compiler to handle by itself.
Another point of smart pointer is that in use, like a real pointer, it can support operations such as fetching content *, pointer access member ->, etc. Therefore, these operators need to be overloaded.
(1) Operator overloading of "->", "asterisk", "bool"
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std; //smart pointer //1. Use it like a pointer //2. Will release resources by itself class CStudent { public: CStudent() { } void test() { cout << "CStudent" << endl; } private: char* m_pszBuf; int m_nSex; }; //Create a class that utilizes the mechanism of the class's construction and destructor (in and out of scope automatically invoked by the compiler) //To solve the problem of automatic resource release //Smart pointer prototype for managing resources class CSmartPtr { public: //It must be a heap object, because it uses the construction and destructor to manage resources CSmartPtr(CStudent* pObj) { m_pObj = pObj; } ~CSmartPtr() { if (m_pObj != nullptr) { delete m_pObj; } } //Need to figure out a way to make the object act like a pointer //In order to make sp write like a pointer //Overload the -> operator, return the pointer of the inner class, the pointer type is CStudent //In this case, sp can use the returned pointer to point to the CStudent object and point to its internal member function, writing: //CSmartPtr sp(new CStudent()); sp->test(); CStudent* operator->() { return m_pObj; } //Overload *, returning a reference to CStudent, making (*sp).test(); true CStudent& operator*() { return *m_pObj; } //Overload bool type, if (sp) {} operator bool() { return m_pObj != nullptr; } //& can also take the address private: CStudent* m_pObj;//Put resources into smart pointer classes and manage them }; int main(int argc, char* argv[]) { //Here you can complete the automatic release of resources, which is to put the object into the object CSmartPtr sp(new CStudent()); sp->test(); (*sp).test(); if (sp) { } //However, it doesn't look like a pointer return 0; }
(2) However, when the above operations such as pointer assignment are encountered, the program will crash. How to solve this?
1) Overloading of = operator, copy construction is not allowed (not recommended)
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std; //smart pointer //1. Use it like a pointer //2. Will release resources by itself class CStudent { public: CStudent() { } void test() { cout << "CStudent" << endl; } private: char* m_pszBuf; int m_nSex; }; //Create a class that utilizes the mechanism of the class's construction and destructor (in and out of scope automatically invoked by the compiler) //To solve the problem of automatic resource release //Smart pointer prototype for managing resources class CSmartPtr { public: //It must be a heap object, because it uses the construction and destructor to manage resources CSmartPtr(CStudent* pObj) { m_pObj = pObj; } ~CSmartPtr() { if (m_pObj != nullptr) { delete m_pObj; } } //Copy is prohibited CSmartPtr& operator=(CSmartPtr&) = delete; //Disable = operator overloading CSmartPtr(CSmartPtr&) = delete; //Need to figure out a way to make the object act like a pointer //In order to make sp write like a pointer //Overload the -> operator, return the pointer of the inner class, the pointer type is CStudent //In this case, sp can use the returned pointer to point to the CStudent object and point to its internal member function, writing: //CSmartPtr sp(new CStudent()); sp->test(); CStudent* operator->() { return m_pObj; } //Overload *, returning a reference to CStudent, making (*sp).test(); true CStudent& operator*() { return *m_pObj; } //Overload bool type, if (sp) {} operator bool() { return m_pObj != nullptr; } //& can also take the address private: CStudent* m_pObj;//Put resources into smart pointer classes and manage them }; int main(int argc, char* argv[]) { //Put in block scope for debugging { //Here you can complete the automatic release of resources, which is to put the object into the object CSmartPtr sp(new CStudent()); CSmartPtr sp3(new CStudent()); //The operator overloading of the = sign will cause a crash and prevent a crash //Anti-crash writing: CSmartPtr(CSmartPtr&) = delete; //sp3 = sp; //The pointer can be assigned, but it will crash after running here //Anti-crash writing: CSmartPtr& operator=(CSmartPtr&) = delete; //CSmartPtr sp2 = sp;//copy construction, the default is shallow copy } //To solve the crash caused by the copy construction above, the method: //1. Do not allow = operator overloading, copy construction (not very recommended) //2. Use copy and move syntax (to prevent multiple releases of resources) //sp->test(); //(*sp).test(); //if (sp) //{ // //} //However, it doesn't look like a pointer return 0; }
2) Use the syntax of copy and move (to prevent the resource from being released multiple times, but it may cause the original sp to be lost and deleted in the move construction)
Assign the pointer of object 1 to object 2, but object 1 will be lost in auto_ptr 98, the defect is obvious
#include <iostream> #include <vector> #include <algorithm> #include <functional> using namespace std; //smart pointer //1. Use it like a pointer //2. Will release resources by itself class CStudent { public: CStudent() { } void test() { cout << "CStudent" << endl; } private: char* m_pszBuf; int m_nSex; }; //Create a class that utilizes the mechanism of the class's construction and destructor (in and out of scope automatically called by the compiler) //To solve the problem of automatic resource release //Smart pointer prototype for managing resources class CSmartPtr { public: //It must be a heap object, because it uses the construction and destructor to manage resources CSmartPtr(CStudent* pObj) { m_pObj = pObj; } ~CSmartPtr() { if (m_pObj != nullptr) { delete m_pObj; } } //Copy is prohibited //CSmartPtr& operator=(CSmartPtr&) = delete; //Use copy-move syntax (to prevent multiple releases of resources) CSmartPtr& operator=(CSmartPtr& sp) { //m_pObj is not empty delete content if (m_pObj!=nullptr) { delete m_pObj; } m_pObj = sp.m_pObj;//assign sp.m_pObj = nullptr;//No need for the original return *this; } //Disable = operator overloading CSmartPtr(CSmartPtr&) = delete; //Need to figure out a way to make the object act like a pointer //In order to make sp write like a pointer //Overload the -> operator, return the pointer of the inner class, the pointer type is CStudent //In this case, sp can use the returned pointer to point to the CStudent object and point to its internal member function, writing: //CSmartPtr sp(new CStudent()); sp->test(); CStudent* operator->() { return m_pObj; } //Overload *, returning a reference to CStudent, making (*sp).test(); true CStudent& operator*() { return *m_pObj; } //Overload bool type, if (sp) {} operator bool() { return m_pObj != nullptr; } //& can also take the address private: CStudent* m_pObj;//Put resources into smart pointer classes and manage them }; int main(int argc, char* argv[]) { //Put in block scope for debugging { //Here you can complete the automatic release of resources, which is to put the object into the object CSmartPtr sp(new CStudent()); CSmartPtr sp3(new CStudent()); //The operator overloading of the = sign will cause a crash and prevent a crash //Anti-crash writing: CSmartPtr(CSmartPtr&) = delete; sp3 = sp; //The pointer can be assigned, but it will crash after running here //Anti-crash writing: CSmartPtr& operator=(CSmartPtr&) = delete; //CSmartPtr sp2 = sp;//copy construction, the default is shallow copy } //To solve the crash caused by the copy construction above, the method: //1. Do not allow = operator overloading, copy construction (not very recommended) //2. Use the syntax of copy and move (to prevent the resource from being released multiple times, but it may cause the original sp to be lost and deleted in the move construction) //Assign the pointer of object 1 to object 2, but object 1 will be lost in auto_ptr 98, the defect is obvious //3. Combined with the previous reference counting and copy-on-write //sp->test(); //(*sp).test(); //if (sp) //{ // //} //However, it doesn't look like a pointer return 0; }
3) Combined with the previous reference counting and copy-on-write, the writing method of the new smart pointer
Recommended spelling
And listen to the next breakdown!
5. Learning video address: The principle of smart pointer
6. Study Notes: Principle Notes of Smart Pointer