C++ smart pointer,unique_ptr,shared_ptr

smart pointer

與一般的pointer相比,smart pointer的優勢在於我們不需要顯式地呼叫delete(ptr)來釋放它所佔用的記憶體。只要smart pointer一落在可視範圍之外,smart pointer的destructor便會自動地釋放動態分配的內存。

std::unique_ptr

我們可以將std::unique_ptr看成是raw pointer的container。當我們希望一塊資源只能被一個指標所存取時,我們就可以使用std::unique_ptr

C++不允許std::unique_ptr被複製。所以如果我們想要轉移資源的擁有者,就必須借助std::move來達成。

如:

//會出錯,不能複製unique_ptr
 unique_ptr<A> ptr2 = ptr1;   
//可以成功執行
unique_ptr<A> ptr2 = move(ptr1); 

TensorRT/samples/opensource/sampleMNIST/sampleMNIST.cpp中有下面這麼一段:

template <typename T>
using SampleUniquePtr = std::unique_ptr<T, samplesCommon::InferDeleter>;

參照std::unique_ptr的文檔

template <
    class T,
    class Deleter
> class unique_ptr<T[], Deleter>;

可以得知samplesCommon::InferDeleter是這裡指定的deleter,在該unique_ptr被摧毀或指向別處時,deleter就會負責清理該unique_ptr所佔用的空間。

Deleter

上面定義的SampleUniquePtr是這麼被調用的:

SampleUniquePtr<nvcaffeparser1::IBinaryProtoBlob>
        mMeanBlob;

其中nvcaffeparser1::IBinaryProtoBlob來自TensorRT/include/NvCaffeParser.h

//!
//! \class IBinaryProtoBlob
//!
//! \brief Object used to store and query data extracted from a binaryproto file using the ICaffeParser.
//!
//! \see nvcaffeparser1::ICaffeParser
//!
//! \warning Do not inherit from this class, as doing so will break forward-compatibility of the API and ABI.
//!
class IBinaryProtoBlob
{
public:
    virtual const void* getData() TRTNOEXCEPT = 0;
    virtual nvinfer1::DimsNCHW getDimensions() TRTNOEXCEPT = 0;
    virtual nvinfer1::DataType getDataType() TRTNOEXCEPT = 0;
    virtual void destroy() TRTNOEXCEPT = 0;

protected:
    virtual ~IBinaryProtoBlob() {}
};

samplesCommon::InferDeleter定義於TensorRT/samples/common/common.h

struct InferDeleter
{
    template <typename T>
    void operator()(T* obj) const
    {
        if (obj)
        {
            obj->destroy();
        }
    }
};

它會調用T型別(此處即為nvcaffeparser1::IBinaryProtoBlob)物件的destroy函數來銷毀該物件。

關於Deleter

Deleter must be FunctionObject or lvalue reference to a FunctionObject 
or lvalue reference to function, callable with an argument of 
type unique_ptr<T, Deleter>::pointer

Deleter必須是一個functor,或是functor的左值引用,又或是函數的左值引用。由於InferDeleteroverride了()這個運算子,所以它確實是一個functor。

std::unique_ptr::get

TensorRT/parsers/caffe/caffeParser/caffeParser.cpp的函數CaffeParser::parse中使用了std::unique_ptr::get的語法:

mModel = std::unique_ptr<trtcaffe::NetParameter>(new trtcaffe::NetParameter);
//bool readBinaryProto(trtcaffe::NetParameter* net, const char* file, size_t bufSize)
/**/readBinaryProto(mModel.get(), modelFile, mProtobufBufferSize))/**/

參考std::unique_ptr::get

std::unique_ptr::get
pointer get() const noexcept;

其作用為:

Returns the stored pointer.

即回傳std::unique_ptr內儲存的指標。

std::shared_ptr

std::shared_ptr亦是raw pointer的container。當我們希望一塊資源能被多個pointer所存取時,我們就會用到std::shared_ptr

C++允許多個shared_ptr指向同一塊資源。並且shared_ptr還自帶了計數功能,即,每當一個新的shared_ptr指向該資源時,reference count就會加一;而每當一個shared_ptr指向別處或是被銷毀時,reference count就會減一。

TensorRT/samples/opensource/sampleMNIST/sampleMNIST.cpp中對shared_ptr的使用:

std::shared_ptr<nvinfer1::ICudaEngine> mEngine{nullptr}; //!< The TensorRT engine used to run the network
//...
mEngine = std::shared_ptr<nvinfer1::ICudaEngine>(
        builder->buildEngineWithConfig(*network, *config), samplesCommon::InferDeleter());

以下是shared_pointer的constructor的定義,可與上面的代碼相對照:

template< class Y, class Deleter >
shared_ptr( Y* ptr, Deleter d );

參考連結

Smart Pointers in C++

auto_ptr, unique_ptr, shared_ptr and weak_ptr

std::unique_ptr

std::unique_ptr::get

std::shared_ptr

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值