2013-12-19 31 views
6

我有一些遺留時代的代碼在工作,它需要一個雙指針併爲其分配內存。它縮短的例子會是這個樣子:使用共享指針與在另一個函數中分配的內存

struct LegacyObj 
{ 
    int a; 
    double b; 
}; 

void LegacyAllocator(LegacyObj** ppObj) 
{ 
    *ppObj = (LegacyObj*)malloc(sizeof(LegacyObj)); 
} 

void LegacyDeleter(LegacyObj** ppObj) 
{ 
    free(*ppObj); 
} 

實際LegacyAllocator功能〜100線和混合讀取文件與創建LegacyObj指針鏈表,是不是我可以現在就重寫。然而,我想讓這個函數的使用更安全一點,避免因例外& tc引起的任何內存泄漏。我提出的第一個解決方案是把它包裝在一個類中,並處理調用ctor/dtor中的遺留函數。

class RAIIWrapper 
{ 
public: 
    RAIIWrapper() 
     :obj{nullptr} 
    { 
     ::LegacyAllocator(&obj); 
    } 
    RAIIWrapper(RAIIWrapper&& that) 
     : obj{ that.obj} 
    { 
     that.obj = nullptr; 
    } 
    RAIIWrapper& operator=(RAIIWrapper&& that) 
    { 
     RAIIWrapper copy{std::move(that)}; 
     std::swap(obj, copy.obj); 
     return *this; 
    } 
    ~RAIIWrapper() 
    { 
     ::LegacyDeleter(&obj); 
    } 

private: 
    LegacyObj* obj; 
}; 

但我很好奇 - 是有辦法做到這一點使用std::shared_ptrstd::unique_ptr?我無法想出一個解決方案,而不必將原始指針保持傳遞給LegacyAllocator。

+0

'unique_ptr'和'shared_ptr'不採取分配器,他們只需要刪除者。您將使用'LegacyAllocator(&obj)'自己分配指針,併爲調用'operator()' – David

回答

3

是的,你可以使用一個定製刪除與std::unique_ptrstd::shared_ptr,例如:

struct Deleter { 
    void operator()(LegacyObj *p) const { 
    LegacyDeleter(&p); 
    } 
}; 

std::unique_ptr<LegacyObj, Deleter> MakeLegacyObj() { 
    LegacyObj *p = 0; 
    LegacyAllocator(&p); 
    return std::unique_ptr<LegacyObj, Deleter>(p); 
} 

std::unique_ptr<LegacyObj, Deleter> p = MakeLegacyObj(); 

而且,作爲正確地指出的@戴夫,這一點也適用shared_ptr太:

std::shared_ptr<LegacyObj> p = MakeLegacyObj(); 
+1

和'std :: shared_ptr​​「中的'LegacyDeleter(&p)'的'unique_ptr' /'shared_ptr'創建一個刪除函數p = MakeLegacyObj();'也可以工作 – David

+0

@Dave:是的,好點。 – vitaut

+0

謝謝,看起來像創建一個自定義刪除函數是我想念。 –

0

您可以使用unique_ptr刪除記憶,但你必須,因爲內存使用malloc而不是new分配提供一個自定義Deleter類。

更好的是,將分配代碼更改爲使用new,而不是使用unique_ptr。如果你走這條路,你可以讓分配器返回一個unique_ptr而不是一個指向內存的指針。

假設你需要提供自己的定製刪除,這裏是你可以做的一種方式:

template <typename T> 
class MallocDeleter 
{ 
public: 
    void operator() (T* obj) const 
    { 
    LegacyDeleter (*obj); 
    } 
}; 

typedef std::unique_ptr <LegacyObj, MallocDeleter <LegacyObj>> unique_legacy_ptr; 

你也大概可以提供通過調用LegacyAllocator分配make_unique_legacy型功能,而不必初始化你自己unique_ptr

0

您可以創建unique_ptr的工廠功能,如下所示:

typedef void(* LegacyDeleterType)(LegacyObj*); 
typedef std::unique_ptr<LegacyObj,LegacyDeleterType> UniqueLegacyPtr; 

UniqueLegacyPtr makeUniqueLegacyObj() 
{ 
    LegacyObj * p = nullptr; 
    LegacyAllocator(&p); 
    return UniqueLegacyPtr(p, [](LegacyObj*p){ LegacyDeleter(&p); }); 
} 

現在,您可以用它來創建unique_ptr S和你也可以分配給shared_ptr S的捕捉在建設自動定製刪除:

int main() 
{ 
    auto unique = makeUniqueLegacyObj(); 
    std::shared_ptr<LegacyObj> shared = makeUniqueLegacyObj(); 
}