In practice, the intelligent pointer unique_ptr series in c ++ -- std: unique_ptr construction (try to use std: make_unique in C ++ 14, instead of new)

Source: Internet
Author: User

In practice, the intelligent pointer unique_ptr series in c ++ -- std: unique_ptr construction (try to use std: make_unique in C ++ 14, instead of new)

The previous blog is an opening part of unique_ptr, which is to briefly explain why unique_ptr is used. Compared with traditional pointers, intelligent pointers only offer advantages.

Let's start with the construction!

Take a look at these constructor methods:

default (1) constexpr unique_ptr() noexcept;from null pointer (2)   constexpr unique_ptr (nullptr_t) noexcept : unique_ptr() {}from pointer (3)    explicit unique_ptr (pointer p) noexcept;from pointer + lvalue deleter (4)   unique_ptr (pointer p,    typename conditional
  
   ::value,D,const D&> del) noexcept;from pointer + rvalue deleter (5)   unique_ptr (pointer p,    typename remove_reference
   
    ::type&& del) noexcept;move (6)    unique_ptr (unique_ptr&& x) noexcept;move-cast (7)   template 
    
       unique_ptr (unique_ptr
     
      && x) noexcept;move from auto_ptr (8)  template 
      
        unique_ptr (auto_ptr&& x) noexcept;copy (deleted!) (9) unique_ptr (const unique_ptr&) = delete;
      
     
    
   
  

The methods for constructing unique_ptr are as follows:
First look at 1 2 3 4 5 8

# Include
  
   
# Include
   
    
Int main () {std: default_delete
    
     
D; std: unique_ptr
     
      
U1; std: unique_ptr
      
        U2 (nullptr); std: unique_ptr
       
         U3 (new int); std: unique_ptr
        
          U4 (new int, d); std: unique_ptr
         
           U5 (new int, std: default_delete
          
            (); Std: unique_ptr
           
             U8 (std: auto_ptr
            
              (New int); std: cout <"u1:" <(u1? "Not null": "null") <'\ n'; if (u1! = Nullptr) {std: cout <"* u1:" <* u1 <std: endl;} std: cout <"u2: "<(u2? "Not null": "null") <'\ n'; if (u2! = Nullptr) {std: cout <"* u2:" <* u2 <std: endl;} std: cout <"u3: "<(u3? "Not null": "null") <'\ n'; if (u3! = Nullptr) {std: cout <"* u3:" <* u3 <std: endl;} std: cout <"u4: "<(u4? "Not null": "null") <'\ n'; if (u4! = Nullptr) {std: cout <"* u4:" <* u4 <std: endl;} std: cout <"u5: "<(u5? "Not null": "null") <'\ n'; if (u5! = Nullptr) {std: cout <"* u5:" <* u5 <std: endl;} std: cout <"u8: "<(u8? "Not null": "null") <'\ n'; if (u8! = Nullptr) {std: cout <"* u8:" <* u8 <std: endl;} return 0;} output: u1: nullu2: nullu3: not null * u3:-842150451u4: not null * u4:-842150451u5: not null * u5:-842150451u8: not null * u8:-842150451
            
           
          
         
        
       
      
     
    
   
  

The analysis shows that constructor 1 2 is equivalent to nullptr, while others are junk values.

Constructor 3 is perhaps the most familiar form, such as int * p = new int;

Here the constructor 4 5 uses a std: default_delete. What is this?
Std: default_delete is the default destruction policy used by std: unique_ptr when no deleter is specified.
1) The non-specialized default_delete uses delete to deallocate memory for a single object.
2) A partial specialization for array types that uses delete [] is also provided.

Constructor 8 constructs unique_ptr from other smart pointers.

The following are the six and seven constructor methods that use the std: move syntax. We will add and demonstrate the following:

# Include
  
   
# Include
   
    
Int main () {std: default_delete
    
     
D; std: unique_ptr
     
      
U1; std: unique_ptr
      
        U2 (nullptr); std: unique_ptr
       
         U3 (new int); std: unique_ptr
        
          U4 (new int, d); std: unique_ptr
         
           U5 (new int, std: default_delete
          
            (); Std: unique_ptr
           
             U8 (std: auto_ptr
            
              (New int); std: cout <"u1:" <(u1? "Not null": "null") <'\ n'; if (u1! = Nullptr) {std: cout <"* u1:" <* u1 <std: endl;} std: cout <"u2: "<(u2? "Not null": "null") <'\ n'; if (u2! = Nullptr) {std: cout <"* u2:" <* u2 <std: endl;} std: cout <"u3: "<(u3? "Not null": "null") <'\ n'; if (u3! = Nullptr) {std: cout <"* u3:" <* u3 <std: endl;} std: cout <"u4: "<(u4? "Not null": "null") <'\ n'; if (u4! = Nullptr) {std: cout <"* u4:" <* u4 <std: endl;} std: cout <"u5: "<(u5? "Not null": "null") <'\ n'; if (u5! = Nullptr) {std: cout <"* u5:" <* u5 <std: endl;} std: cout <"u8: "<(u8? "Not null": "null") <'\ n'; if (u8! = Nullptr) {std: cout <"* u8:" <* u8 <std: endl;} std: unique_ptr
             
               U6 (std: move (u5); std: cout <"u6:" <(u6? "Not null": "null") <'\ n'; if (u6! = Nullptr) {std: cout <"* u6:" <* u6 <std: endl;} std: cout <"now, let us see u5: "; std: cout <" u5: "<(u5? "Not null": "null") <'\ n'; if (u5! = Nullptr) {std: cout <"* u5:" <* u5 <std: endl;} std: unique_ptr
              
                U7 (std: move (u6); std: cout <"u7:" <(u7? "Not null": "null") <'\ n'; if (u7! = Nullptr) {std: cout <"* u7:" <* u7 <std: endl;} std: cout <"now, let us see u6: "; std: cout <" u6: "<(u6? "Not null": "null") <'\ n'; if (u6! = Nullptr) {std: cout <"* u6:" <* u6 <std: endl;} return 0 ;}// output: // u1: null // u2: null // u3: not null // * u3:-842150451 // u4: not null // * u4:-842150451 // u5: not null // * u5:-842150451 // u8: not null // * u8:-842150451 // u6: not null // * u6:-842150451 // now, let us see u5: u5: null // u7: not null // * u7:-842150451 // now, let us see u6: u6: null
              
             
            
           
          
         
        
       
      
     
    
   
  

The most important thing to note here is:
U5 was not null, but after std: move, u5 becomes null,
U6 is not empty at the beginning. After std: move, u6 is also empty.

It also needs to be emphasized that, when removing the pointer from the reference, it is necessary to verify whether the pointer is null. if the pointer is null and then the value operation is performed, the program will crash. Serious bug.

If I write it now, I will stop. You will say that I am a title party, but I am not.
Continue:
Std: make_unique is not included in c ++ 11, which is the content of C ++ 14:
There are three constructors:
Template <class T, class... Args>
Unique_ptr make_unique (Args &&... Args );

Template <class T>
Unique_ptr make_unique (std: size_t size );

Template <class T, class... Args>
/* Unspecified */make_unique (Args &&... Args) = delete;

# Include
  
   
# Include
   
    
Struct Vec3 {int x, y, z; Vec3 (): x (0), y (0), z (0) {} Vec3 (int x, int y, int z): x (x), y (y), z (z) {} friend std: ostream & operator <(std: ostream & OS, vec3 & v) {return OS <'{' <"x:" <v. x <"y:" <v. y <"z:" <v. z <'}' ;}}; int main () {// Use the default constructor. std: unique_ptr
    
     
V1 = std: make_unique
     
      
(); // Use the constructor that matches these arguments std: unique_ptr
      
        V2 = std: make_unique
       
         (0, 1, 2); // Create a unique_ptr to an array of 5 elements std: unique_ptr
        
          V3 = std: make_unique
         
           (5); std: cout <"make_unique
          
            (): "<* V1 <'\ n' <" make_unique
           
             (0, 1, 2): "<* v2 <'\ n' <" make_unique
            
              (5): "<'\ n'; for (int I = 0; I <5; I ++) {std :: cout <"" <v3 [I] <'\ n' ;}}// output: // make_unique
             
               (): {X: 0 y: 0 z: 0} // make_unique
              
                (0, 1, 2): {x: 0 y: 1 z: 2} // make_unique
               
                 (5): // {x: 0 y: 0 z: 0} // {x: 0 y: 0 z: 0} // {x: 0 y: 0 z: 0} // {x: 0 y: 0 z: 0} // {x: 0 y: 0 z: 0}
               
              
             
            
           
          
         
        
       
      
     
    
   
  

As you can see, make_unique perfectly passes the parameter to the object's constructor, constructs a std: unique from an original pointer, and returns the created std: unique_ptr. Functions in this form do not support arrays and custom delimiters.

Compared with the direct use of new, the make function reduces code duplication and improves exception security. For std: make_shared and std: allcoated_shared, the generated code is smaller and faster.

At this point, you can refer to the blog http://blog.csdn.net/coolmeme/article/details/43405155

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.