C ++ Program Design Mechanism 3: RAII Mechanism

Source: Internet
Author: User

1. Concept

Resource Acquisition Is Initialization mechanism was first proposed by Bjarne Stroustrup. To solve this problem:

In C ++, if you need to release some resources at the end of the program segment, it is normal that there is no problem, but when an exception is thrown, the statement for releasing resources will not be executed. So Bjarne Stroustrup thought that the destructor of the object placed in this program segment (stack frame) was the place where the resource release code could be run, because stack winding ensures that all their destructor are executed. Benefits of moving initialization and resource release to a packaging class:

Ensures normal resource release
Eliminating the lengthy and repetitive cleaning logic that is not necessarily executed in exception handling, thus ensuring code exception security.
Simplified code size.
2. Application scenarios

1) File Operations

We can use this mechanism to package file operations to complete an exceptionally secure file class. In implementation, note that the replication constructor and value assignment are privatized. This is done through a private inheritance class, because these two operations do not make sense here. Of course, this is not what RAII requires.

/*
* ===================================================== ==============================================

*
* Filename: file. cpp
*
* Description: RAII for files
*
* Version: 1.0
* Created: 05/09/2011 06:57:43
* Revision: none
* Compiler: g ++
*
* Author: gnuhpc (http://blog.csdn.net/gnuhpc), warmbupt@gmail.com
*
* ===================================================== ==========================================================

*/
# Include
# Include
# Include

Using namespace std;
Class NonCopyable
{
Public:
NonCopyable (){};
Private:
NonCopyable (NonCopyable const &); // private copy constructor
NonCopyable & operator = (NonCopyable const &); // private assignment operator
};

Class SafeFile: NonCopyable {
Public:
SafeFile (const char * filename): fileHandler (fopen (filename, "w + "))
{
If (fileHandler = NULL)
{
Throw runtime_error ("Open Error! ");
}
}
~ SafeFile ()
{
Fclose (fileHandler );
}

Void write (const char * str)
{
If (fputs (str, fileHandler) = EOF)
{
Throw runtime_error ("Write Error! ");
}
}

Void write (const char * buffer, size_t num)
{
If (num! = 0 & fwrite (buffer, num, 1, fileHandler) = 0)
{
Throw runtime_error ("Write Error! ");
}
}
Private:
FILE * fileHandler;
SafeFile (const SafeFile &);
SafeFile & operator = (const SafeFile &);
};

Int main (int argc, char * argv [])
{
SafeFile testVar ("foo. test ");
TestVar. write ("Hello RAII ");
} The structure of C ++ determines its native support for RAII. in Java, it is unknown when objects are destroyed. Therefore, try-finally can be used in Java for related processing.

2) intelligent pointer Simulation

A more complex example is to simulate smart pointers. The abstracted RAII class implements an operator * and directly returns the stored pointer:

Now we have a class:

Class Example {
SomeResource * p _;
SomeResource * p2 _;
Public:
Example ():
P _ (new SomeResource ()),
P2 _ (new SomeResource ()){
Std: cout <"Creating Example, allocating SomeResource! ";
}

Example (const Example & other ):
P _ (new SomeResource (* other. p _)),
P2 _ (new SomeResource (* other. p2 _)){}

Example & operator = (const Example & other ){
// Self assignment?
If (this = & other)
Return * this;

* P _ = * other. p _;
* P2 _ = * other. p2 _;
Return * this;
}

~ Example (){
Std: cout <"Deleting Example, freeing SomeResource! ";
Delete p _;
Delete p2 _;
}
};
Assume that an exception may occur during SomeResource creation. When the resource to which p _ points is created but p2 _ points to fails to be created, the entire instance of Example fails to be created, the resource to which p _ points has memory leakage.

The following method can be used as an alternative:

Example (): p _ (0), p2 _ (0)
{
Try {
P _ = new SomeResource ();
P2 _ = new SomeResource ("H", true );
Std: cout <"Creating Example, allocating SomeResource! ";
}
Catch (...){
Delete p2 _;
Delete p _;
Throw;
}
}

However, we can use an object to call the features of the Destructor when it leaves a domain, complete initialization in the constructor, and complete cleaning in the destructor, put the pointer to be operated and protected into RAII as a member variable.

Template
Class RAII {
T * p _;
Public:
Explicit RAII (T * p): p _ (p ){}

~ RAII (){
Delete p _;
}

Void reset (T * p ){
Delete p _;
P _ = p;
}

T * get () const {
Return p _;
}

T & operator * () const {
Return * p _;
}

Void swap (RAII & other ){
Std: swap (p _, other. p _);
}

Private:
RAII (const RAII & other );
RAII & operator = (const RAII & other );
};
In specific use, we put the protected pointer Someresource in RAII:

 

Class Example {
RAII p _;
RAII p2 _;
Public:
Example ():
P _ (new SomeResource ()),
P2 _ (new SomeResource ()){}

Example (const Example & other)
: P _ (new SomeResource (* other. p _)),
P2 _ (new SomeResource (* other. p2 _)){}

Example & operator = (const Example & other ){
// Self assignment?
If (this = & other)
Return * this;

* P _ = * other. p _;
* P2 _ = * other. p2 _;
Return * this;
}

~ Example (){
Std: cout <"Deleting Example, freeing SomeResource! ";
}
};
Now, even if p _ succeeds but p2 _ fails, the RAII destructor will be called in Stack winding to ensure that the Someresource pointed to by p _ is destructed. This method is different from the interface corresponding to the pointer type that needs to be combined in Example 1. The interface is not encapsulated here. Of course, in Example 1, you can also provide a getPointer function to directly provide the handle.

In fact, in Example, there is no need for destructor, because the RAII class will take care of all this. This is a bit like auto_ptr. This article does not discuss the topic of smart pointers in depth.

3) Lock Operation

/*
* ===================================================== ========================================================== =

*
&

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.