Unique_ptr's member functions are covered almost entirely in the previous blog, and there's actually a kick-off, that Std::unique_ptr::get_deleter
It is literally obvious that you get deleter:
Returns the stored deleter
The stored deleter is a callable object. A functional call to this object with a single argument of member type pointer are expected to delete the managed object, a ND is automatically called when the Unique_ptr are itself destroyed, assigned a new value, or resetted while non-empty.
See examples directly:
#include <iostream>#include <memory>classState_deleter {//A deleter class with state intCount_; Public: State_deleter (): Count_ (0) {}Template<classT>void operator() (t* p) {STD::cout<<"[Deleted #"<< ++count_ <<"]\n";DeleteP }};intMain () {State_deleter del;STD::unique_ptr<int> P;//uses default deleter //Alpha and Beta use independent copies of the deleter: STD::unique_ptr<int, State_deleter> Alpha (New int);STD::unique_ptr<int, State_deleter> Beta (New int, Alpha.get_deleter ());return 0;}
Run the program and output the results:
[Deleted #1]
[Deleted #1]
It is explained that at the end of the function, the Alpha Beta destructor is called, and the destructor is the class we define ourselves.
Add an action to Alpha Beta on the above code:
intMain () {State_deleter del;STD::unique_ptr<int> P;//uses default deleter //Alpha and Beta use independent copies of the deleter: STD::unique_ptr<int, State_deleter> Alpha (New int);STD::unique_ptr<int, State_deleter> Beta (New int, Alpha.get_deleter ());STD::cout<<"Resetting alpha ..."; Alpha.reset (New int);STD::cout<<"Resetting beta ..."; Beta.reset (New int);return 0;}
Output:
Resetting Alpha ... [Deleted #1]
Resetting beta ... [Deleted #1]
[Deleted #2]
[Deleted #2]
Description after the Reset method, a custom destructor is also called ~
Then continue adding the code:
#include <iostream>#include <memory>classState_deleter {//A deleter class with state intCount_; Public: State_deleter (): Count_ (0) {}Template<classT>void operator() (t* p) {STD::cout<<"[Deleted #"<< ++count_ <<"]\n";DeleteP }};intMain () {State_deleter del;STD::unique_ptr<int> P;//uses default deleter //Alpha and Beta use independent copies of the deleter: STD::unique_ptr<int, State_deleter> Alpha (New int);STD::unique_ptr<int, State_deleter> Beta (New int, Alpha.get_deleter ());//Gamma and Delta share the deleter "del" (deleter type is a reference!): STD::unique_ptr<int, State_deleter&> Gamma (New int, Del);STD::unique_ptr<int, State_deleter&> Delta (New int, Gamma.get_deleter ());STD::cout<<"Resetting alpha ..."; Alpha.reset (New int);STD::cout<<"Resetting beta ..."; Beta.reset (New int);STD::cout<<"Resetting gamma ..."; Gamma.reset (New int);STD::cout<<"Resetting delta ..."; Delta.reset (New int);return 0;}
Output:
Resetting Alpha ... [Deleted #1]
Resetting beta ... [Deleted #1]
Resetting gamma ... [Deleted #1]
Resetting Delta ... [Deleted #2]
[Deleted #3]
[Deleted #4]
[Deleted #2]
[Deleted #2]
Here we focus on Delta, which is used by reference.
There is one more place to note:
The order of the destruction is the opposite of the Order of construction.
Go on:
#include <iostream>#include <memory>classState_deleter {//A deleter class with state intCount_; Public: State_deleter (): Count_ (0) {}Template<classT>void operator() (t* p) {STD::cout<<"[Deleted #"<< ++count_ <<"]\n";DeleteP }};intMain () {State_deleter del;STD::unique_ptr<int> P;//uses default deleter //Alpha and Beta use independent copies of the deleter: STD::unique_ptr<int, State_deleter> Alpha (New int);STD::unique_ptr<int, State_deleter> Beta (New int, Alpha.get_deleter ());//Gamma and Delta share the deleter "del" (deleter type is a reference!): STD::unique_ptr<int, State_deleter&> Gamma (New int, Del);STD::unique_ptr<int, State_deleter&> Delta (New int, Gamma.get_deleter ());STD::cout<<"Resetting alpha ..."; Alpha.reset (New int);STD::cout<<"Resetting beta ..."; Beta.reset (New int);STD::cout<<"Resetting gamma ..."; Gamma.reset (New int);STD::cout<<"Resetting delta ..."; Delta.reset (New int);//std::cout << "calling Gamma/delta deleter ...";Gamma.get_deleter () (New int); Alpha.get_deleter () = State_deleter ();//A brand new deleter for Alpha //Additional deletions when unique_ptr objects reach out of scope //(in inverse order of declaration) return 0;}
Output at this time:
Output:
Resetting Alpha ... [Deleted #1]
Resetting beta ... [Deleted #1]
Resetting gamma ... [Deleted #1]
Resetting Delta ... [Deleted #2]
Calling Gamma/delta deleter ...
[Deleted #3]
[Deleted #4]
[Deleted #5]
[Deleted #2]
[Deleted #1]
Finally, one more:
#include <iostream>#include <memory>using namespace STD;voidDeleter (int* ptr) {Deleteptr PTR =nullptr;STD::Clog<<"shared_ptr Delete the pointer."<<STD:: Endl;}intMainvoid) {//define function type typedef void(*TP) (int*);typedef Decltype(deleter) * DP;usingup =void(*) (int*);STD::shared_ptr<int> SPI (New int(Ten), deleter);STD::shared_ptr<int> Spi2 (New int, deleter); Spi2 =STD::make_shared<int> ( the);STD::cout<<"*SPI ="<< *spi <<STD:: Endl;STD::cout<<"*SPI2 ="<< *spi2 <<STD:: Endl;//unique_ptr is a template function that requires a type of delete (deleter), which is then passed in to the specific filter STD::unique_ptr<int,Decltype(Deleter) *> UPI (New int( -), deleter);STD::unique_ptr<int, Tp> Upi2 (New int( -), deleter);STD::unique_ptr<int, Dp> Upi3 (New int( -), deleter);STD::unique_ptr<int, Up> Upi4 (New int( *), deleter);STD::cout<<"*upi ="<< *upi <<STD:: Endl;STD::cout<<"*UPI2 ="<< *upi2 <<STD:: Endl;STD::cout<<"*UPI3 ="<< *upi3 <<STD:: Endl;STD::cout<<"*UPI4 ="<< *upi4 <<STD:: Endl;return 0;}//output://shared_ptr Delete the pointer.//*spi = Ten//* spi2 =//* UPI =//* upi2 =//* Upi3 =//* upi4 =//shared_ptr Delete the pointer.//shared_ptr Delete the pointer.//shared_ptr Delete the pointer.//shared_ptr Delete the pointer.//shared_ptr Delete the pointer.
Just analyze these two sentences:
std::shared_ptr<int>std::make_shared<int>(15);
This is the time to invoke the deleter delete!
Smart pointer unique_ptr series in combat C + +-Get_deleter method of unique_ptr (custom delete)