2017-08-26 74 views
4

我有一些處理對象創建和銷燬的C API,它提供了:createObject(...)destroy(...)。我想將它包裝到一些更現代化的構建/銷燬機制中,並將它們與智能指針一起使用。我恐怕在某些時候我會忘記摧毀這個物體,否則會發生一些異常。環繞C使用智能指針創建和銷燬函數

我知道定製刪除功能shared_ptr,但我不能明確地調用new,因爲createOjbect函數處理初始化。

我可以在這種情況下使用STL智能指針嗎?我必須從頭開始在構造函數中實現一個初始化類,在這種情況下在析構函數中進行銷燬和引用計數?

+1

爲什麼你需要在你的課堂參考計數器?只需在構造函數中調用createObject,在析構函數中銷燬並提供一些靜態工廠函數,該函數將返回指向您的類的智能指針。智能指針將處理refcounter部分。當你的類最終被破壞時 - 它會自動調用destroy –

+0

createObject返回什麼?需要做些什麼?根據你的答案,可以有改進。 – Yakk

回答

6

std::shared_ptr完全能夠使用cutstom創建者和刪除者創建和刪除對象,但不必使用new您必須使用創建者函數。

讓我們考慮,我們有以下的創造者和刪除器:

typedef struct { 
    int m_int; 
    double m_double; 
} Foo; 

Foo* createObject(int i_val, double d_val) { 
    Foo* output = (Foo*)malloc(sizeof(Foo)); 

    output->m_int = i_val; 
    output->m_double = d_val; 

    puts("Foo created."); 
    return output; 
} 

void destroy(Foo* obj) { 
    free(obj); 
    puts("Foo destroyed.");   
} 

來管理功能創建的Foo一個實例之上,只需做到以下幾點:

std::shared_ptr<Foo> foo(createObject(32, 3.14), destroy); 

使用如果您不希望共享該對象的所有權,則爲開銷std::shared_ptr。在這種情況下,std::unique_ptr要好得多,但這種類型的,你必須定義一個定製刪除仿函數與它可以刪除管理Foo實例:

struct FooDeleter { 
    void operator()(Foo* p) const { 
     destroy(p); 
    } 
}; 
using FooWrapper = std::unique_ptr<Foo, FooDeleter>; 

/* ... */ 

FooWrapper foo(createObject(32, 3.14)); 
+1

我想補充一點,你通常可以通過C的免費作爲刪除功能。 –

1

C++ 17。

template<auto X> using constant_t=std::integral_constant<std::decay_t<decltype(X)>, X> 
template<auto X> constexpr constant_t<X> constant{}; 
template<class T, auto dtor> using smart_unique_ptr=std::unique_ptr< T, constant_t<dtor> >; 

現在,假設你有一個C API包裝BobBob* createBob(some_args...)destroyBob(Bob*)

using unique_bob=smart_unique_ptr< Bob, destroyBob >; 
unique_bob make_unique_bob(some_args args){ 
    return unique_bob(createBob(args)); 
} 

一個unique_bob可以隱式移入shared_ptr<Bob>

額外假設的位可以使C++ 14此項工作:

template<class T, void(*dtor)(T*)> using smart_unique_ptr=std::unique_ptr< T, std::integral_constant<decltype(dtor),dtor> >; 

其假設析構函數簽名是void(T*)

在C++ 11中,您必須編寫一個新的無狀態函數指針調度程序,用於零開銷unqiue ptrs。

+0

我喜歡你的解決方案'std :: integral_constant'。 – Akira

0

發佈了我的情況下完整的解決方案:

基於@晃的建議,我把它包使用共享的指針,因爲我想拉姆達這個對象在許多宮殿共享和:

// coming from some API: 
struct SomeStruct; 
bool initializedata(SomeStruct **data); 
bool destorycdata(SomeStruct **data); 

class SomeStructWrapper 
{ 
public: 
    SomeStructWrapper() 
    { 
     SomeStruct* data; 
     if(initializedata(&data)) 
     { 
      m_data = std::shared_ptr<SomeStruct>(data, [](SomeStruct* ptr){ 
       destorycdata(&ptr); 
      }); 
     } 
     else 
     { 
      throw std::runtime_error("Data was not initalized"); 
     } 
    } 

    const SomeStruct* operator->() const {return m_data.get();} 
    SomeStruct* operator->() {return m_data.get();} 

private: 
    std::shared_ptr<SomeStruct> m_data; 
};