Article directory
1. What is RAII memory management technology?
- After C++ introduced the exception mechanism,Jumps in code execution flowIt becomes unpredictable, if you use ordinary pointers for memory management, it is difficult to avoidmemory leakThe problem (execution flow jumps cause the heap area resources cannot be released)
- RAII technology refers toUse the life cycle of objects to manage memory resources, as far as the management of memory resources in the heap area is concerned, it refers to: encapsulating the pointer in the class, inclass object constructionGet heap resources, whenAt the end of the class object's lifetime,passclass object destructorAutomatically complete the release of heap area resources, such class objects aresmart pointer
- Smart pointers can effectively avoid the problem of memory leaks in development, and at the same time save developers a lot of time and effort
2. Smart pointer
- Smart pointers in the C++11 standard library are mainly divided into three categories:
unique_ptr
unique_ptr
Copying between objects is not allowed, ieanunique_ptr
objectmanageA heap memory resource, is a one-to-one relationshipunique_ptr
The simple implementation principle of :
//不允许拷贝的智能指针
//delfunc是堆区资源释放函数,用于调用delete或者delete[]
template<class T,class delfunc>
class unique_ptr
{
public:
unique_ptr(T * ptr = nullptr)
:_ptr(ptr)
{
}
~unique_ptr()
{
if (_ptr)
{
delfunc del;
del(_ptr);
std::cout << "delete" << std::endl;
}
}
//让智能指针可以像指针一样被使用
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
//禁止unique_ptr对象间的拷贝
unique_ptr(const unique_ptr<T, delfunc>& unptr) = delete;
unique_ptr<T, delfunc>& operator=(const unique_ptr<T, delfunc>& unptr) = delete;
private:
T* _ptr;
};
- When using pointers to manage heap resources, we will let them point tosingle objectorarray of objects,single object
delete
completes resource release witharray of objectsThe design purpose of the class template parameters to be useddelete[]
to complete resource release is to distinguish the above two situations, allowing users to passunique_ptr
delfunc
design functorway to choose betweendelete
anddelete[]
shared_ptr
shared_ptr
It is a smart pointer that allows copying, butshared_ptr
when copying occurs between objects, it will appearmultiple smart pointersSimultaneous managementsame heap memorysituation,shared_ptr
throughreference countThe technology avoids the situation where the same heap resource is released multiple times:- Implementation ideas for reference counting:
shared_ptr
Encapsulate a pointer internally toint * recount
maintainreference count variable- Whenever an
shared_ptr
object performsConstruct and apply for heap resourcesAt the same time, apply for an int variable in the heap area as theshared_ptr
heap area resource pointed to by the objectreference count variable - Whenever
shared_ptr
copied, along withint * recount
the copy, and then letreference count variableJust add one (the implementation of assignment overloading also needs to be consideredreference count variableminus one andHeap resource releaseThe problem) - Whenever
shared_ptr
destructor,reference count variableminus one, ifreference count variableIf it is reduced to 0, the heap resources will be released
shared_ptr
The simple implementation principle of :
//允许拷贝的智能指针,利用引用计数解决内存管理冲突
//delfunc是堆区资源释放函数,用于调用delete或者delete[]
template<class T, class delfunc>
class shared_ptr
{
public:
//构造智能指针(同时创建引用计数变量)
shared_ptr(T* ptr = nullptr)
:_ptr(ptr),
_recount(new int(1))
{
}
shared_ptr(const shared_ptr<T, delfunc>& shptr)
: _ptr(shptr._ptr),
_recount(shptr._recount)
{
//智能指针拷贝增加引用计数
(*_recount)++;
}
shared_ptr<T, delfunc>& operator=(const shared_ptr<T, delfunc>& shptr)
{
if (_ptr != shptr._ptr)
{
//智能指针指向改变,其先前指向的堆区内存和引用计数变量需要处理
Release();
//完成智能指针拷贝并增加引用计数
_ptr = shptr._ptr;
_recount = shptr._recount;
++(*_recount);
}
return (*this);
}
~shared_ptr()
{
Release();
}
//让智能指针可以像指针一样被使用
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
T* getptr() const
{
return _ptr;
}
private:
//将资源释放函数进行封装,方便复用
//引用计数减一,若引用计数减为0则释放资源
void Release()
{
//引用计数减一
--(*_recount);
//引用计数为0则释放资源
if (*_recount == 0)
{
if (_ptr)
{
delfunc del;
del(_ptr);
std::cout << "delete" << std::endl;
}
//同时注意释放引用计数变量
delete _recount;
}
}
private:
T* _ptr;
int* _recount;
};
shared_ptr
Inside the class, we also need to solve thereference count variablebroughtthread safetyproblem, not discussed here
circular reference problem
shared_ptr
used inself referencing structwill appear inThe problem that the object cannot be destructed:
template<class T>
class deletefunc
{
public:
void operator()(T* ptr)
{
delete ptr;
}
};
// 循环引用
struct ListNode
{
int _val;
shared_ptr<ListNode,deletefunc<ListNode>> _next;
shared_ptr<ListNode,deletefunc<ListNode>> _prev;
~ListNode()
{
cout << "~ListNode()" << endl;
}
};
// 循环引用
void test_shared_cycle()
{
share_ptr<ListNode, deletefunc<ListNode>> n1(new ListNode);
share_ptr<ListNode, deletefunc<ListNode>> n2(new ListNode);
n1->_next = n2;
n2->_prev = n1;
}
- When
test_shared_cycle()
the function is executed, both linked list nodes areCannot be destructed normally,shared_ptr
causing a circular reference problem: n1
The destruction of the node depends on the destruction of the pointern2
in the node , the destruction of the pointer in the node depends on the destruction of the node, the destruction of the node depends on the destruction of the pointer in the node , and the destruction of the pointer in the node depends on the node Destruction. This reciprocation constitutes a circular dependency that causes both nodes to fail to be released._prev
n2
_prev
n2
n2
n1
_next
n1
_next
n1
weak_ptr
It is designed to solve the circular reference problem
weak_ptr
weak_ptr
smart pointerDoes not participate in the application and release of heap memory, and will not increase the reference count of a specific memory block (its function is similar to that of a normal pointer), and supportsweak_ptr
copy construction and assignment of reference parametersshared_ptr
weak_ptr
Simple implementation principle:
//用于配合share_ptr的使用用于循环引用的场景
//delfunc是堆区资源释放函数,用于调用delete或者delete[]
//weak_ptr不参与资源的申请和释放
template<class T, class delfunc>
class weak_ptr
{
public:
weak_ptr()
:_ptr(nullptr)
{
}
~weak_ptr()
{
}
weak_ptr(const weak_ptr<T, delfunc>& wptr)
:_ptr(wptr._ptr)
{
}
weak_ptr(const share_ptr<T, delfunc>& shptr)
:_ptr(shptr.getptr())
{
}
weak_ptr<T, delfunc>& operator=(const weak_ptr<T, delfunc>& wptr)
{
_ptr = wptr._ptr;
return (*this);
}
weak_ptr<T, delfunc>& operator=(const share_ptr<T, delfunc>& shptr)
{
_ptr = shptr.getptr();
return (*this);
}
//让智能指针可以像指针一样被使用
T& operator*()
{
return *_ptr;
}
T* operator->()
{
return _ptr;
}
private:
T* _ptr;
};
- existself referencing struct
weak_ptr
The problem of circular references can be avoided by using