Smart pointer in boost

Source: Internet
Author: User
Boost Introduction

According to the boost website, boost is "a free and portable C ++ library for Synchronous evaluation. Boost is a model of the new class library, especially those databases that can work well with the iso c ++ standard library." However, boost is not just a collection of libraries. It is also a rapidly developing developer community where developers create, use, and participate in discussions about boost libraries. The boost community not only maintains this library, but also provides a place for its users and designers to learn and communicate with each other. This library is a typical example of design stability. Before the next version is released, you may not even feel that it is worth improving. Joining a discussion group on the boost email list (or active in it, or just looking at how others discuss it) is a great way to improve your understanding of Library Design Problems and Solutions. Boost also provides a list of boost user emails with a high number of users. The list focuses on the use of boost libraries. The quality of the boost library and its technical standards are amazing. The boost portability standard ensures that your library works normally when you move your code from one platform to another. The latest version is boost 1.25.0, from smart pointers to regular expressions to portable thread libraries. Boost currently supports 35 libraries, all of which have been tested and used by members of the community. These libraries are free of charge, and many of them have been used for commercial application software development.

Boost is one of the most powerful in the C ++ community. Among the 2000 members, many of them are the world's top C ++ programmers. These members have been involved for a long time because they love working with programmers who have the best way of thinking. At the same time, they know that their efforts will definitely have a huge impact on the C ++ community, because most of the content you see in boost will become candidates for integrating with the future C ++ standard.

The best way to understand boost is to browse the boost library. In this article, I will introduce you to the smart pointer library smart_ptr of boost. Smart_ptr is a good example that reflects boost innovation and perfect design. I suggest you visit the boost site () to obtain the details of the other 34 libraries in the boost set.

Smart pointer

One of the relatively small boost libraries is smart_ptr. Smart_ptr is one of the libraries I think will stop moving forward in the C ++ standard. This article discusses the smart_ptr library in boost. But first, I will start with an introduction to smart pointers.

Introduction to smart pointers in 30 seconds

Smart pointers are classes that store pointers to dynamically allocated (HEAP) objects. In addition to the ability to automatically delete pointed objects at the right time, their working mechanism is similar to the built-in pointer of C ++. Smart pointers are especially useful in the face of exceptions because they can ensure correct destruction of dynamically allocated objects. They can also be used to track dynamically allocated objects shared by multiple users.

In fact, smart pointers can do many other things, such as processing thread security, providing write-time replication, ensuring the protocol, and providing remote interaction services. Some methods can be used to create general smart pointers for these ESP (extremely smart pointers), but they have not covered recent years. (For details, refer to [1]. Alexandrescu is considering submitting his c ++ library Loki to boost ).

Most smart pointers are used for lifetime control and phase control. They use operator-> and operator * to generate the original pointer, so that the smart pointer looks like a normal pointer.

Such a class comes from the standard library: STD: auto_ptr. It is designed to solve the problem of resource ownership, but lacks support for the number of references and arrays. In addition, STD: auto_ptr transfers ownership when being copied. In most cases, you need more and/or different features. In this case, you need to add the smart_ptr class.

Smart_ptr class

The smart pointers in boost include:

. Scoped_ptr is used to process the unique ownership of a single object. Unlike STD: auto_ptr, scoped_ptr can be copied.

. Scoped_array, similar to scoped_ptr, but used to process

. Shared_ptr, allowing shared object ownership

. Shared_array, which allows sharing array ownership

Scoped_ptr

Scoped_ptr smart pointer is different from STD: auto_ptr because it does not pass ownership. In fact, it explicitly prohibits any attempt to do so! This is important in any situation where you need to ensure that the pointer has only one owner at any time. If scoped_ptr is not used, you may prefer STD: auto_ptr. Let's take a look at the following code:

Auto_ptr myownstring?

(New string ("This is mine to keep! "));

Auto_ptr noitsmine?(Myownstring?);

Cout <* myownstring <Endl; // boom

This Code cannot be compiled because the ownership of the string is passed to noitsmine. This is not a design defect of STD: auto_ptr-it is a feature. Even so, when you need myownstring to achieve the expected effect of the above Code, you can use scoped_ptr:

Scoped_ptr myownstring?

(New string ("This is mine to keep for real! "));

// Compiler error-there is no copy constructor.

Scoped_ptr tryingtotakeitanyway?

(Myownstring?);

Scoped_ptr performs this operation by inheriting from boost: noncopyable (you can view the boost. Utility library ). Do not copy the class declaration to copy the constructor and declare the value assignment operator as private.

Scoped_array

Scoped_array and scoped_ptr are obviously equivalent, but they are used to process arrays. The standard library is not considered at this point-unless you can certainly use STD: vector, this is acceptable in most cases.

Usage is similar to scoped_ptr:

Typedef tuples: tupleint> arraytuple?;

Scoped_array myarray?(New arraytuple?[10]);

Tuples: Get <0> (myarray?[5]) = "The Library tuples is also part of Boost ";

Tuple is a set of elements-for example, double, triple, and four. A typical usage of tuple is to return multiple values from the function. The boost tuple library can be considered to be a two-fold extension of the standard library. Currently, it works with nearly 10 tuple elements. Tuple stream, comparison, assignment, and package unloading are supported. For more information about the boost tuple library, see [2] and [3].

When scoped_array is out of bounds, delete [] will be called correctly. This avoids a common error, that is, calling the incorrect operator Delete.

Shared_ptr

Here is a reference number smart pointer that you cannot find in the standard library. Most people should have had the experience of using smart pointers, and there have been many articles about reference numbers. One of the most important details is how the reference count is executed-insert, which means that you add the reference count function to the class or are not inserted, it means you do not do this. Boost shared_ptr is non-insert type, which uses a reference counter allocated from the heap. There is a lot of discussion about the provision of parameterization policies that makes it extremely suitable for any situation, but the final result of the discussion is the decision to oppose focusing on availability. However, do not expect the discussion to end.

Shared_ptr completes what you want: It is responsible for deleting the pointee object to which it points when you do not use the instance, and it can freely share the pointee object it points ).

Void printifstring?(Const any & any ){

If (const shared_ptr * s =

Any_cast> (& any )){

Cout <** S <Endl;

}

}

Int main (INT argc, char * argv [])

{

STD: vector stuff;

Shared_ptr sharedstring1?

(New string ("share me. By the way,

Boost. Any is another useful boost

Library "));

Shared_ptr sharedstring2?

(Sharedstring1?);

Shared_ptr Sharedint1 ?

(New int (42 ));

Shared_ptr Sharedint2 ?

(Sharedint1?);

Stuff. push_back (sharedstring1?);

Stuff. push_back (sharedstring2?);

Stuff. push_back (sharedint1?);

Stuff. push_back (sharedint2?);

// Print the strings

For_each (stuff. Begin (), stuff. End (),

Printifstring?);

Stuff. Clear ();

// The pointees of the shared_ptr's

// Will be released on leaving scope

// Pointee of shared_ptr will be released after it leaves this range.

Return 0;

}

The any Library provides a way to store everything [2] HYPERLINK "file: // C: Documents % 20and % 20settingsadministrator desktop my % 20documents ents new cujhtml#04karlsson % 22% 20l" [4]. What is required in the include type is that they are copyconstructible. The Destructor cannot be triggered here, and they should be allocable. How do we store and transmit "all things "? No different types (read as void *) can involve all things, but this will mean leaving type security (and knowledge) behind. The any database provides type security. All types that meet the any requirement can be assigned a value, but you need to know the unlock type when unlocking. Any_cast is the key to unlock the value stored by any. any_cast and dynamic_cast work in a similar way-pointer type conversion succeeds or fails by returning a null pointer, therefore, the type conversion of the value assignment type throws an exception (bad_any_cast) and fails.

Shared_array

Shared_array and shared_ptr share the same role, but they are used to process arrays.

Shared_array mystrings?(New base [20]);

In-depth Implementation of shared_ptr

It is very easy to create a simple smart pointer. However, it is difficult to create a smart pointer that can be passed in most compilers. However, it is more difficult to consider abnormal security when creating an ECS instance. Boost: shared_ptr is all done. The following shows how it achieves it. (Note: All include, disconnect compiler processing, and some content of this implementation is omitted, but you can find them in boost. smart_ptr ).

First, define a class: Obviously, smart pointers are (almost always) templates.

Template Class shared_ptr {

The public interface is:

Explicit shared_ptr (T * p = 0): Px (p ){

// Fix: Prevent leak if new throws

Try {Pn = new long (1 );}

Catch (...) {checked_delete (p); throw ;}

}

Now, two things in the constructor are easy to ignore. The constructor is explicit, and can carry a parameter just like most constructor. It is worth noting that the heap allocation of the number of references is protected by a try-Catch Block. Without this, you will get a defective smart pointer. If the number of references is not successfully allocated, it will not be able to complete its own work normally.

~ Shared_ptr () {dispose ();}

The Destructor executes another important task: if the number of references drops to zero, it should be able to safely delete the objects (pointee) pointed ). The Destructor delegates this important task to another method: dispose.

Void dispose () {If (-* Pn = 0)

{Checked_delete (PX); Delete PN ;}}

As you can see, the number of references (PN) is decreasing. If it is reduced to zero, checked_delete is called on the indicated object (PX), and the reference number (PN) is also deleted.

So what functions does checked_delete perform? This convenient function (which you can find in boost. Utility) ensures that the pointer represents a complete type. Is this in your smart pointer class?

This is the first value assignment operator:

Template Shared_ptr & operator =

(Const shared_ptr & R ){

Share (R. PX, R. pn );

Return * this;

}

This is a member template. If not, there are two situations:

1. If there is no parameterized copy constructor, the type value base = derived is invalid.

2. If there is a parameterized copy constructor, the type assignment takes effect, but an unnecessary temporary smart_ptr is created at the same time.

This once again shows why you should not add your own smart pointer to a very good reason-none of these are obvious problems.

The actual work of the value assignment operator is done by the share function:

Void share (T * RPX, long * RPN ){

If (Pn = RPN) {// Q: Why not PX = RPX?

// A: fails when both = 0

+ * RPN; // done before dispose () in case

// RPN transitively dependent on

// * This (bug reported by Ken Johnson)

Dispose ();

Px = RPX;

Pn = RPN;

}

}

Note that self-assignment (more accurately, self-sharing) is done by comparing the number of references, rather than by pointer. Why? Because both of them can be zero, but not necessarily the same.

Template Shared_ptr

(Const shared_ptr & R): Px (R. px) {// never throws

+ + * (Pn = R. pn );

}

This version is a template-based copy structure and function. Let's take a look at the discussion above to understand why we should do this.

The assignment operator and the assignment constructor also have a non-template version here:

Shared_ptr (const shared_ptr & R ):

// Never throws

Px (R. px) {++ * (Pn = R. pn );}

Shared_ptr & operator =

(Const shared_ptr & R ){

Share (R. PX, R. pn );

Return * this;

}

The reset function resets the indicated object (pointee) Just like its name ). When you are about to leave the scope, if you need to destroy the indicated object (pointee), it will be very convenient for you to complete, or simply make the value in the cache invalid.

Void reset (T * p = 0 ){

// Fix: Self-assignment safe

If (PX = P) return;

If (-* Pn = 0)

{Checked_delete (PX );}

Else {// allocate new reference

// Counter

// Fix: Prevent leak if new throws

Try {Pn = new long ;}

Catch (...){

// Undo Effect of-* PN above

// Meet effects guarantee

+ + * PN;

Checked_delete (P );

Throw;

} // Catch

} // Allocate new reference counter

* Pn = 1;

Px = P;

} // Reset

Please pay attention to the measures to avoid potential memory leakage and maintain exceptional security.

In this way, you have an operator that enables smart pointers to exert their "intelligence:

// Never throws

T & operator * () const {return * PX ;}

// Never throws

T * operator-> () const {return PX ;}

// Never throws

T * Get () const {return PX ;}

This is just a comment: some smart pointers implement conversion from the type conversion operator to the T * operator. This is not a good idea. This will often hurt you. Although get looks uncomfortable here, it stops the compiler from playing games with you.

I remember Andrei Alexandrescu said, "If your smart pointer works like a dumb pointer, It is a dumb pointer ." That's right.

There are some very good functions here. Let's take them as the end of this article.

Long use_count () const

{Return * PN;} // never throws

Bool unique () const

{Return * Pn = 1;} // never throws

The function name already describes its functions, right?

About boost. there are many other things to note about smart_ptr (for example, STD: swap and STD: less), which are determined together with STD: auto_ptr to ensure compatibility and convenience ), due to space limitations, we cannot continue with the introduction. For more information, see smart_ptr.hpp of boost distribution. Even if there is no other content, do you think he is indeed a very intelligent pointer?

Related Article

E-Commerce Solutions

Leverage the same tools powering the Alibaba Ecosystem

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

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.