Smart pointer class reference count
A common implementation technique for smart pointers (smart pointer) is to use reference counts (reference count). The smart pointer class links a counter to the object that the class points to, and the reference count tracks how many objects in the class have pointers to the same object. The reference count is 0 o'clock, and the object is deleted.
The basic usage rules are:
Each time a new object of the class is created, the pointer is initialized and the reference count is set to 1. When an object is created as a copy of another object, the copy constructor copies the pointer and increments the value corresponding to the reference count. When an object is assigned, the assignment operator reduces the value of the reference count of the object referred to by the left operand (deletes the object if the reference count is reduced to 0) and increases the value of the reference count of the object that the right operand refers to. Finally, when the destructor is called, the destructor reduces the value of the reference count, and if the count is reduced to 0, the base object is deleted.
There are two classic strategies for implementing reference Counting: The introduction of auxiliary classes (which contain reference-counting types)and the use of handle classes (separating reference-counting types).
Strategy 1: Reference counting classes
All members of this class are private. We don't want users to use the U_ptr class, so it doesn't have any public members. Set the Hasptr class to friends so that its members can access the members of the U_ptr.
The U_ptr class holds pointers and usage counts, each Hasptr object points to a U_ptr object, and uses a count to track the number of Hasptr objects that point to each U_ptr object. The only functions defined by U_PTR are constructors and destructors, constructors copy pointers, and destructors delete them. The constructor also resets the usage count to 1, indicating that a Hasptr object points to the U_ptr object.
classu_ptr{friend classHasptr;int*ip;intUse U_ptr (int*p): IP (P) {} ~u_ptr () {Deleteip }};classhasptr{ Public: Hasptr (int*p,inti): _ptr (NewU_ptr (P)), _val (i) {} hasptr (Consthasptr& obj): _ptr (Obj._ptr), _val (obj._val) {++_ptr->use; } hasptr&operator=(Consthasptr&); ~hasptr () {if(--_ptr->use = =0)Delete_ptr; }Private: u_ptr* _ptr;int_val;};
A hasptr constructor that takes a pointer and an int value creates a new U_ptr object with its pointer parameters. When the Hasptr constructor finishes executing, the Hasptr object points to a newly assigned U_ptr object that stores the given pointer. The usage count in the new u_ptr is 1, which means that only one Hasptr object points to it.
The copy constructor copies the members from the parameter and increases the value of the usage count. When the copy constructor finishes executing, the newly created object points to the same U_ptr object as the original object, and the usage count of the U_ptr object is added by 1.
The destructor checks the usage count of the U_ptr base object. If you use a count of 0, this is the last Hasptr object that points to the U_ptr object, in which case the Hasptr destructor deletes its u_ptr pointer. Deleting the pointer causes a call to the U_ptr destructor, and the U_ptr destructor deletes the int base object.
assignment and reference counting
First, the usage count in the right operand is added to 1, then the usage count of the left operand object is reduced by 1 and the usage count is checked. As in a destructor, if this is the last object that points to the U_ptr object, the object is deleted, which in turn revokes the Int base object. After the current value in the left operand is reduced by 1 (possibly undoing the object), the pointer is copied from the RHS to the object. The assignment returns a reference to the object as usual.
HasPtr& HasPtr::operator=(const HasPtr &rhs){ // increment use count on rhs first if0) delete// if use count goes to 0 on this object,delete it // copy the U_Ptr object // copy the int member return *this;}
This assignment operator prevents the assignment of RHS by adding 1 to the usage count of the left operand before reducing its usage count.
If the left and right operands are the same, the effect of the assignment operator is to subtract 1 from the usage count of the U_ptr base object plus 1.
Value type class
When you copy a value object, you get a different new copy. Changes made to the copy are not reflected on the original object and vice versa. The String class is an example of a value type class.
To make a pointer member behave like a value, you must copy the object that the pointer points to when you copy the Hasptr object:
The copy constructor no longer duplicates the pointer, it assigns a new int object, and initializes the object to hold the same value as the copied object. Each object holds a different copy of its own int value. Because each object holds its own copy, the destructor removes the pointer unconditionally.
The assignment operator does not need to assign a new object, it simply must remember to assign a new value to the object to which the pointer is pointing, rather than assigning a value to the pointer itself.
//复制构造函数定义HasPtr(const HasPtr &orig):ptr(newint (*orig.ptr)), val(orig.val) { }//赋值函数定义HasPtr& HasPtr::operator=(const HasPtr &rhs){ // copy the value pointed to // copy the int return *this;}
Strategy 2: Handle class
A common technique in C + + is to define wrapper (cover) classes or handle classes. Handle Classes Store and manage base class pointers. The type of the object that the pointer refers to can vary, which can point to both the base class type object and the derived type object. The user accesses the inheritance hierarchy operation through the handle class. Because a handle class uses pointers to perform operations, the behavior of a virtual member changes at run time based on the type of object the handle is actually bound to. Therefore, the user of the handle can get dynamic behavior without worrying about the management of pointers.
There are two important design considerations for wrapping a handle to an inheritance hierarchy:
* As with any class that holds pointers, you must determine what to do with replication control. A handle that wraps an integrated hierarchy usually behaves like a smart pointer or a value.
* The handle class determines whether the handle interface masks or does not mask the inheritance hierarchy, and if the inheritance hierarchy is not masked, the user must understand and use the objects in the base hierarchy.
A smart pointer is a class that simulates a pointer action. All smart pointers are overloaded with and * operators.
classsmart_pointer{ Public://default Constructor:unbound HandleSmart_pointer (): _p (0), _use (New STD:: size_t (1)){}//attaches A handle to a copy of the Base objectSmart_pointer (Constbase&);//copy Control Manage the use count and pointersSmart_pointer (Constsmart_pointer& i): _p (i._p), _use (i._use) {++*use;} ~smart_pointer () {decr_use ();} smart_pointer&operator=(Constsmart_pointer&);//member Access Operators ConstBase *operator()Const{if(_p)return_p;Else Throw STD:: Logic_error ("Unbound Base"); }ConstBase &operator*()Const{if(_p)return*p;Else Throw STD:: Logic_error ("Unbound Base"); }Private: Base *_p;STD:: size_t *_use;voidDecr_use () {if(--*use = =0) {Delete_p;Delete_use; } }};
PTR template class for OpenCV
The smart pointer ptr template class in OPENCV is the implementation technique of the handle class using the separated reference count type.
Taking OPENCV face recognition as an example, three kinds of algorithms in face recognition are realized: Eigenface, Fisherface and LBP-based algorithm. These three algorithms are also encapsulated into three classes: Eigenfaces, Fisherfaces, LBPH class, all three classes derive from the Facerecognizer class, and the Facerecognizer class derives from the algorithm class. The Facerecognizer class is an abstract base class.
OpenCV is the object that uses a generic handle class PTR to manage the Facerecognizer class.
Template<TypeName_tp>classCv_exports ptr{ Public://! Empty ConstructorPtr ();//! Take ownership of the pointer. The associated reference counter is allocated and set to 1PTR (_tp* _obj);//! calls release ()~ptr ();//! copy constructor. Copies the members and calls AddRef ()PTR (Constptr& ptr);Template<TypeName_tp2> Ptr (Constptr<_tp2>& ptr);//! copy operator. Calls Ptr.addref () and release () before copying the membersptr&operator= (Constptr& ptr);//! increments the reference counter voidAddRef ();//! decrements the reference counter. If it reaches 0, Delete_obj () is called voidRelease ();//! deletes the object. Override if needed voidDelete_obj ();//! returns true IFF Obj==null BOOLEmpty ()Const;//! cast pointer to another type Template<TypeName_tp2> ptr<_tp2> Ptr ();Template<TypeName_tp2>ConstPtr<_tp2> ptr ()Const;//! Helper operators making "ptr<t> ptr" use very similar to "t* ptr"._tp*operator();Const_tp*operator()Const;operator_tp* ();operator Const_tp* ()Const; _tp* obj;//< The object pointer. int* REFCOUNT;//< The associated reference counter};
When creating an object of the Facerecognizer derived class eigenfaces, we can rely on the handle class PTR to ensure that the Eigenfaces object is automatically freed when we put the Eigenfaces object inside the PTR object.
Ptr<FaceRecognizer> model = createEigenFaceRecognizer(num_components, threshold);
When using Createeigenfacerecognizer to dynamically create an Eigenfaces object, immediately put it in Ptr < Facerecognizer > for management. Immediately after the resource has been acquired, the management object is placed in, and the management object uses the destructor to ensure that the resource is freed.
Ptr<FaceRecognizer> createEigenFaceRecognizer(intdouble threshold){ returnnew Eigenfaces(num_components, threshold);}
We note that in the Createeigenfacerecognizer implementation source, we return the dynamic creation of Eigenfaces objects and implicitly convert them to PTR.
reprint Please indicate the author Jason Ding and its provenance
GitHub Blog Home page (http://jasonding1354.github.io/)
CSDN Blog (http://blog.csdn.net/jasonding1354)
Jane Book homepage (http://www.jianshu.com/users/2bd9b48f6ea8/latest_articles)
Baidu Search jasonding1354 access to my blog homepage
PTR template classes for "C + +" smart pointer classes and OPENCV