程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 實戰c++中的智能指針unique_ptr系列-- unique_ptr的get_deleter方法(自定義刪除器)

實戰c++中的智能指針unique_ptr系列-- unique_ptr的get_deleter方法(自定義刪除器)

編輯:C++入門知識

實戰c++中的智能指針unique_ptr系列-- unique_ptr的get_deleter方法(自定義刪除器)


unique_ptr的成員函數在上一篇博客中幾乎全部涵蓋,其實還有一個很有踢掉,即std::unique_ptr::get_deleter

字面已經很明顯了,就獲得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 is expected to delete the managed object, and is automatically called when the unique_ptr is itself destroyed, assigned a new value, or resetted while non-empty.

直接看例子:

#include 
#include 

class state_deleter {  // a deleter class with state
    int count_;
public:
    state_deleter() : count_(0) {}
    template 
    void operator()(T* p) {
        std::cout << "[deleted #" << ++count_ << "]\n";
        delete p;
    }
};

int main() {
    state_deleter del;

    std::unique_ptr p;   // uses default deleter

    // alpha and beta use independent copies of the deleter:
    std::unique_ptr alpha(new int);
    std::unique_ptr beta(new int, alpha.get_deleter());
    return 0;
}

運行程序,輸出結果:
[deleted #1]
[deleted #1]
說明了,在函數結束的時候,alpha beta的析構函數被調用了,而且析構函數是我們自己定義的類。

在上面的代碼上加入對alpha beta的操作:

int main() {
    state_deleter del;

    std::unique_ptr p;   // uses default deleter

    // alpha and beta use independent copies of the deleter:
    std::unique_ptr alpha(new int);
    std::unique_ptr beta(new int, alpha.get_deleter());


    std::cout << "resetting alpha..."; alpha.reset(new int);
    std::cout << "resetting beta..."; beta.reset(new int);

    return 0;
}

輸出:
resetting alpha…[deleted #1]
resetting beta…[deleted #1]
[deleted #2]
[deleted #2]
說明在reset方法後,也調用了自定義的析構~

再繼續添加代碼:


#include 
#include 

class state_deleter {  // a deleter class with state
    int count_;
public:
    state_deleter() : count_(0) {}
    template 
    void operator()(T* p) {
        std::cout << "[deleted #" << ++count_ << "]\n";
        delete p;
    }
};

int main() {
    state_deleter del;

    std::unique_ptr p;   // uses default deleter

                              // alpha and beta use independent copies of the deleter:
    std::unique_ptr alpha(new int);
    std::unique_ptr beta(new int, alpha.get_deleter());

    // gamma and delta share the deleter "del" (deleter type is a reference!):
    std::unique_ptr gamma(new int, del);
    std::unique_ptr 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;
}

輸出:
resetting alpha…[deleted #1]
resetting beta…[deleted #1]
resetting gamma…[deleted #1]
resetting delta…[deleted #2]
[deleted #3]
[deleted #4]
[deleted #2]
[deleted #2]
這裡我們重點關注delta,這裡使用的是按引用傳遞。
還有一個地方需要說明:
析構的順序與構造的順序相反~~

go on:


#include 
#include 

class state_deleter {  // a deleter class with state
    int count_;
public:
    state_deleter() : count_(0) {}
    template 
    void operator()(T* p) {
        std::cout << "[deleted #" << ++count_ << "]\n";
        delete p;
    }
};

int main() {
    state_deleter del;

    std::unique_ptr p;   // uses default deleter

                              // alpha and beta use independent copies of the deleter:
    std::unique_ptr alpha(new int);
    std::unique_ptr beta(new int, alpha.get_deleter());

    // gamma and delta share the deleter "del" (deleter type is a reference!):
    std::unique_ptr gamma(new int, del);
    std::unique_ptr 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;
}

此時輸出:
//輸出:
//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]

最後再來一個:

#include   
#include   

using namespace std;

void deleter(int* ptr) {
    delete ptr;
    ptr = nullptr;
    std::clog << "shared_ptr delete the pointer." << std::endl;
}

int main(void) {

    //定義函數類型  
    typedef void(*tp) (int*);
    typedef decltype (deleter)* dp;
    using up = void(*) (int*);

    std::shared_ptr spi(new int(10), deleter);
    std::shared_ptr spi2(new int, deleter);
    spi2 = std::make_shared(15);

    std::cout << "*spi = " << *spi << std::endl;
    std::cout << "*spi2 = " << *spi2 << std::endl;

    //unique_ptr是模板函數需要刪除器(deleter)類型, 再傳入具體的刪除器  
    std::unique_ptr upi(new int(20), deleter);
    std::unique_ptr upi2(new int(25), deleter);
    std::unique_ptr upi3(new int(30), deleter);
    std::unique_ptr upi4(new int(35), 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;

}
//輸出:
//shared_ptr delete the pointer.
//*spi = 10
//* spi2 = 15
//* upi = 20
//* upi2 = 25
//* upi3 = 30
//* upi4 = 35
//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.

只是分析這兩句:

std::shared_ptr spi2(new int, deleter);
spi2 = std::make_shared(15);

這時候會調用deleter刪除器!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved