2012-02-16 71 views
3

我正在從C++ API中導出幾個類的DLL。使用shared_ptr作爲輸出參數

公共類的接口應遵循以下約定:

  • 所有函數返回錯誤代碼。
  • 輸出參數用於附加的返回值。
  • 傳遞指針用於輸出參數。
  • 傳遞const引用用於輸入參數(通過基元類型的值傳遞)。
  • 當客戶端應該取得輸出參數shared_ptr的所有權時使用,否則爲正常指針。

實例接口:

typedef std::shared_ptr<Object> ObjectPtr; 

class APIClass 
{ 
    ErrorCode SetSomething(int i); 
    ErrorCode IsSomethingSet(bool* ask); 
    ErrorCode DoSomething(); 
    ErrorCode GetSomething(ObjectPtr* outObj); 
} 

用法示例:

ErrorCode res; 
ObjectPtr obj; 
res = myApiClass->GetSomething(&obj); 

GetSomething實現:

ErrorCode APIClass::GetSomething(ObjectPtr* outObj) 
{ 
    ObjectPtr temp(new Object(), CleanUpFunction<Object>); 

    // Do something with object temp. 
    ... 

    *outObj= temp; 

    return OK; 
} 

是其保存以這種方式使用的shared_ptr還是有可能的我應該知道的問題?

+1

您是否考慮過使用[exceptions](http://www.parashift.com/c++-faq-lite/exceptions.html)而不是返回錯誤代碼? – 2012-02-16 15:28:21

+0

是的,但我不想使用異常,因爲跨DLL邊界使用它們的限制 – Hoschie0815 2012-02-17 03:06:15

+0

編輯該問題是因爲它太冗長。 – Hoschie0815 2012-02-17 03:08:11

回答

1

這很好,但我會問在這種情況下共享指針是否真的有必要。主要是因爲你不能以任何理智的方式釋放shared_ptr的指針......這可能會在稍後導致問題。而shared_ptr確實意味着未指定或共享所有基礎資源。

我通常記錄的功能和使用這樣的:

// Caller must delete the outObj once done. 
ErrorCode APIClass::GetSomething(Object* & outObj) 
{ 
    // I use auto_ptr so I can release it later... 
    // Mostly I hate auto_ptr, but for this its invaluable. 

    auto_ptr<Object> obj(new Object); 
    ... 
    outObj = obj.release(); 
    return OK; 
} 

這樣,它是由他們想要存儲指針成什麼樣的客戶端,很顯然,該對象的所有權轉移到呼叫者。

客戶端代碼然後可以使用適當的容器。

Object * obj_raw; 
ErrorCode ec = apiClass.GetSomething(obj_raw) 
if(ec!=OK) { .. do something with ec .. } 
shared_ptr<Object> obj(obj_raw); 

auto_ptr<Object> obj(obj_raw); 

scoped_ptr<Object> obj(obj_raw); 

注意,這可以更整潔,如果你改變你的函數定義進行:

// Caller must delete the return value. 
// On error, NULL is returned and e filled in appropriately. 
Object* APIClass::GetSomething(ErrorCode & e) 
{ 
    auto_ptr<Object> obj(new Object); 
    .. 
    e = OK; 
    return obj.release(); 
} 

//Now using it looks like this: 
ErrorCode ec; 
shared_ptr<Object> obj(apiObject.GetSomething(ec)); 
if(!obj) 
{ 
    .. do something with ec .. 
} 
+0

感謝您的回覆。跨越DLL邊界(至少在Windows上)傳遞指針存在問題,例如在DLL中分配內存並在客戶端刪除它。看到這裏:http://msdn.microsoft。COM/EN-US /庫/ ms235460.aspx。這就是爲什麼我在創建shared_ptr時使用在DLL中定義的自定義刪除器(CleanUpFunction )。 – Hoschie0815 2012-02-17 05:47:57

+0

但是,通常你認爲解決方案應該沒問題,據我所知?在這種情況下,稍後不能釋放指針可能會成爲問題,或者您爲什麼想要釋放它? – Hoschie0815 2012-02-17 05:56:27

+0

另外我正在考慮類似於您提到的傳遞錯誤代碼作爲可選參數的替代設計,如下所示:ObjectPtr APIClass :: GetSomething(ErrorCode * e = nullptr)。但還不能確定哪種設計更好。 – Hoschie0815 2012-02-17 05:57:40