2017-02-22 3 views
0

Я просто хочу использовать функцию deleter shared_ptr без использования части shared_ptr. Как и в, я хочу вызвать функцию, когда shared_ptr выходит за пределы области видимости, и отладчик не нуждается в каком-либо указателе, переданном ему.Как использовать shared_ptr только для отправителя?

У меня есть это, но это cheezy.

shared_ptr<int> x(new int, [&](int *me) { delete me; CloseResource(); }); 

Есть ли способ не связывать любой указатель с shared_ptr?

Update: в соответствии с многими предложениями, то unique_ptr путь будет выглядеть следующим образом:

unique_ptr<int, std::function<void(int*)>> x(new int, [&](int *me) {delete me; CloseResource();}); 

Что откровенно выглядит хуже, чем версия shared_ptr, насколько «лучше», как это.

Обновления: для тех, кто любит, используя эту простую сферу закрытия функции вызывающего я сделал это немного проще, вам даже не нужно выделять или освобождать объект:

shared_ptr<int> x(NULL, [&](int *) { CloseResource(); }); 
+1

'CloseResource' должен принимать указатель на ресурс, который он закрывает – Slava

+4

Зачем вам нужен общий указатель. Почему бы просто не полагаться на сам объект, выходящий за рамки? –

+1

Во-первых, использование 'unique_ptr' было бы более эффективным (предполагая, что вы не используете общий ресурс« shared_ptr »). Во-вторых, если вы можете использовать Boost, есть Boost.ScopeExit, который выполняет это. В-третьих, если вы не можете использовать Boost, [вы можете легко сделать свой собственный класс, который делает это] (http://stackoverflow.com/questions/3669833/c11-scope-exit-guard-a-good-idea), чтобы избегайте хакерского использования 'unique_ptr' /' shared_ptr'. – Cornstalks

ответ

3

Это походит на то, что вы может пытаться сделать это перевернуться «УДАЛИТЬ» обязанности «кто-то другой», так что вы больше не придется беспокоиться об этом. Если это так, unique_ptr (не shared_ptr) с настраиваемой Deleter будет работать:

struct Foo final {}; 
Foo* New() { return new Foo; } 
void Delete(Foo* p) { delete p; } 

int main() 
{ 
    auto p = New(); 
    std::unique_ptr<Foo, decltype(&Delete)> up(p, &Delete); 
} 

Есть целый ряд подобных решений перечисленных here; не так много, что можно сделать без дополнительной информации о вашем фактическом API (например, работает ли трюк HANDLE is really a pointer?). И еще больше читайте в The simplest and neatest c++11 ScopeGuard, включая link, к предложению std::unique_resource.

0

Если вы хотите RAII как семантика с лямбдой, может быть, что-то подобное сделает работу?

namespace details { 
    enum class ScopeExitDummy { }; 
} 


template<typename T> 
class scope_exit_t 
{ 
public: 
    inline scope_exit_t(T&& codeChunk_) 
    : m_codeChunk(std::forward<T>(codeChunk_)) { 
    } 

    inline scope_exit_t(scope_exit_t<T>&& rhs_) 
    : m_codeChunk(std::move(rhs_.m_codeChunk)) 
    { 
    } 

    ~scope_exit_t() { 
    m_codeChunk(); 
    } 

private: 
    T m_codeChunk; 
}; 

template<typename T> 
inline scope_exit_t<T> operator+(details::ScopeExitDummy, T&& functor_) { 
    return scope_exit_t<T>{std::forward<T>(functor_)}; 
} 

#define AtScopeExit auto TW_UNIQUE_VARIABLE(_scopeExit) = details::ScopeExitDummy{} + [&] 

А использование, как:

AtScopeExit { 
    CloseResource(); 
}; 

Примечания: TW_UNIQUE_VARIABLE просто макрос, который generares уникального имени переменного, так что код не конфликтует с рукописными декларациями.

#define TW_STR_CONCAT_IMPL(x, y) x##y 
#define TW_STR_CONCAT(x, y) TW_STR_CONCAT_IMPL(x, y) 

#ifdef __COUNTER__ 
    #define TW_UNIQUE_VARIABLE(prefix) TW_STR_CONCAT(prefix, __COUNTER__) 
#else 
    #define TW_UNIQUE_VARIABLE(prefix) TW_STR_CONCAT(prefix, __LINE__) 
#endif 
+0

Да, я мог бы сделать шаблонный класс, но я пытался избежать этого, поскольку все функциональные возможности, которые мне нужны, уже существуют в shared_ptr. Зачем воспроизводить колесо? – stu

+4

Указатель общего назначения не предназначен для того, чтобы просто называть делетера при уничтожении - это намного больше. Его не изобретать колесо, пытаясь прекратить использовать это колесо для создания спагетти. –

+0

Компьютеры - это гораздо больше, но мы используем их только для игр и создания электронных таблиц. Разве не все любят повторное использование? Я просто повторно использую часть существующих функций, и не все. Я действительно удивлен, что не существует решения stl для этой проблемы реального мира, которая не включает в себя выполнение плохих вещей, подобных этому. – stu

Смежные вопросы