2012-02-16 3 views
3

Я работаю над C++ API, который экспортирует несколько классов из DLL.Использование shared_ptr в качестве выходного параметра

интерфейс общественного класса А должен соблюдать следующие условные обозначения:

  • Все функции возвращают код ошибки.
  • Выходные параметры используются для дополнительных возвращаемых значений.
  • Проход по указателю используется для выходных параметров.
  • Ссылка на константу используется для входных параметров (передается по значению для примитивных типов).
  • Когда клиент должен взять на себя ответственность за выходной параметр 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

Считаете ли вы использование [исключений] (http://www.parashift.com/c++-faq-lite/exceptions.html) вместо возврата кодов ошибок? –

+0

Да, но я не хочу использовать исключения из-за ограничений с их использованием через границы DLL. – Hoschie0815

+0

Отредактировал вопрос, потому что он был слишком подробным. – Hoschie0815

ответ

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.ком/EN-US/библиотека/ms235460.aspx. Вот почему я использую пользовательский дебетер, который определен в DLL (CleanUpFunction ) при создании shared_ptr. – Hoschie0815

+0

Но в целом вы думаете, что решение должно быть прекрасным, как я понимаю? В этом случае может возникнуть проблема не в том, чтобы не освободить указатель позже или почему вы хотите его выпустить? – Hoschie0815

+0

Также я думал об альтернативном дизайне, подобном тому, который вы упомянули, передав код ошибки в качестве необязательного параметра: ObjectPtr APIClass :: GetSomething (ErrorCode * e = nullptr). Но не мог решить, какой дизайн лучше. – Hoschie0815