Proxy classes and handle classes in C + +

Source: Internet
Author: User

Pointers are one of the most important features of C in contrast to other languages, and pointers are widely used in C + +, and we use pointers to achieve polymorphism. However, it is well known that the use of pointers must be careful, otherwise it is easy to cause memory leaks Leak. When we have several pointers pointing to the same object, it should be noted that when to release this object:
(1) If the release is too early, then the other pointers still point to the memory, if you use it will cause undefined behavior.
(2) If you do not release the last pointer to this object may be lost, the memory cannot be freed.

To solve this problem in C + + is to set up a class to contain pointers that need to be managed, because these classes are often tied to the manager, so they are called the Handel class, and when people build this Handel class, they generally retain the various features of the pointers it contains, so it is also called the smart pointer s Mart pointer.

The simplest Han del

This Handel is just a container that contains the object pointer, and when the pointer to the object is bound to Handel, there is no need to delete the object manually, and the Handel class is responsible for the destruction of the object (when Handel leaves the scope). This is an example of auto_ptr in STL.

A simple AUTOPTR implementation is given below:

/*
* File:auto_prt.h
* Discription: Smart pointer
* The simplest strategy for pointer storage, in which the pointer is stored in the object when the object is automatically deleted by the destructor pointer
* Autoptr and Pointers are a one-to-one relationship
* usage:autoptr< ClassType > ap_type = autoptr< classtype > (New ClassType ());
* Ap_type->method ();
*/

#ifndef _pattern_autoptr_h
#define _pattern_autoptr_h

#include ". /common/common.h "

Namespace C_toto
{

Template<class T> class Autoptr
{
Public
AUTOPTR (Autoptr<t> & AP): PTR (ap.ptr) {ap.ptr = NULL;}

Autoptr<t> & operator= (Autoptr<t> & AP)
{
if (PTR)
{
Delete ptr;
ptr = NULL;
}
ptr = ap.ptr;
Ap.ptr = NULL;
}

Public
Autoptr (T * p = NULL): PTR (p) {}

~autoptr () {delete ptr;}

BOOL Valid ()
{
if (PTR) return true;
return false;
}

T & Operator* () {return *ptr;}

Const T & operator* () const {return *ptr;}

T * operator-> () {return ptr;}
Const T * operator-> () const {return ptr;}
Private
T * PTR;
};

}; Namespace C_toto

#endif//#ifndef _pattern_autoptr_h

It is important to note that since autoptr and pointers are a one-to-ones relationship, the assignment operators and copy constructors in the Autoptr class must ensure that only a autoptr point to the corresponding pointer, where our strategy is:

The parameters in the AUTOPTR (Autoptr<t> & AP) Autoptr ap are invalidated, and the constructed new autoptr takes over the original autoptr pointer.

Autoptr<t> & operator= (autoptr<t> & AP) = Lvalue If there is a pointer, delete removes the original pointer, takes over the right value of the pointer, and the right value is invalidated.

This simple autoptr can be used for exception handling. When we throw an exception in our function execution, the resources allocated before the exception need to be released manually in the catch, which tends to be omitted.
If we store the allocated resources (often pointers) in autoptr, then the resources are automatically freed when they exceed their function, and autoptr automatically calls their respective destructors.

Reference count handle

The purpose of this handle is to implement a many-to-one relationship between the handle and the object (the case for pointers is that multiple pointers point to the same object), so that we can copy the object's pointer by copying the handle as usual. To ensure that the object can be freed, our handle must know how many other handles are pointing to the current object at the same time, so we introduce a reference counting strategy.

(1) This reference count function cannot be placed in a handle. Because if the handle is copied and its reference information is copied, the reference information of the handle that binds the same pointer cannot be managed uniformly.

(2) It is not appropriate to put the reference count in the object, which requires us to rewrite the existing class. We can create an intermediate class to contain a reference counting function and a pointer that needs to be bound with a handle.

As you can see, this intermediate class and our pointer are a one-to-many relationship, and our handle is a pair-to-multi relationship.

Now let's look at how to implement the basic operations in Handel:

(1) Default constructor

Since the handle now faces only the intermediate class that we added, simply call the default construct of the Intermediate class. In the default constructor for the middle class, we zeroed the pointer and set the reference to one.

(2) Copy constructor

Copy is for a handle, we avoid a copy of the value of the pointer by adding the reference count to it.

(3) Assignment operator

When an assignment is performed between handles, the contents of the handle referred to by the left side are overwritten, so it is necessary to have its reference--(when referenced as a momentary note delete), and then a handle reference to the right of the + + equals sign.
It is meaningless to use a Handel to assign a value to the Handel itself.

(4) destructor

Checks whether the reference count is one at each destructor, and if so, indicates that the current handle is the last handle to hold the pointer, and the delete is required in the destructor.
In fact, we can abstract the reference counting function into a class, which is managed directly by the handle, so we can remove the middle layer and reduce the complexity of the program.

/*
* File:sharedptr
* discription: Added pointer storage Policy with reference count
*/

#ifndef _patterns_sharedptr_h_
#define _patterns_sharedptr_h_

#include ". /common/common.h "

Namespace C_toto
{

Template<class t>
Class Sharedptr;

Class Reference
{
Public
Reference (): Ref_count (new int (1)) {}
Reference (const Reference & R): Ref_count (R.ref_count) {(*ref_count) + +;}

~reference ()
{
(*ref_count)--;
if ((*ref_count) = = 0)
Delete Ref_count;
}

BOOL Only () {return (*ref_count = = 1);}

BOOL Rebind (const Reference & R)
{
(*ref_count)--;
(*r.ref_count) + +;

if (*ref_count = = 0)
{
Delete Ref_count;
Ref_count = R.ref_count;
return true;
}
Ref_count = R.ref_count;
return false;
}

Private
Reference & operator= (const Reference & r_);

int * REF_COUNT;
};

////////////////////////////////////////////////////////////////////////////////

Template<class t>
Class Sharedptr
{
Public
Sharedptr (T * p = NULL): PTR (p) {}

~sharedptr () {if (ref. Only ()) {delete ptr;}}

Sharedptr<t> & operator= (const sharedptr<t> & SP)
{
if (ref. Rebind (SP.REF))
{
Delete ptr;
}
ptr = sp.ptr;
return *this;
}

Private
Reference ref;
T * PTR;
}; Class

}; Namespace C_toto

#endif//#ifndef _patterns_sharedptr_h_

Http://www.cnblogs.com/yc_sunniwell/archive/2010/07/12/1775619.html

Proxy classes and handle classes in C + +

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.