如何仅将shared_ptr用于删除工具?

时间:2017-02-22 17:07:32

标签: c++ shared-ptr

我只想在不使用shared_ptr部分的情况下使用shared_ptr的删除功能。就像在,我想在shared_ptr超出范围并且删除器不需要传递给它的任何指针时调用一个函数。

我有这个,但它很腼腆。

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

有没有办法不将任何指针与shared_ptr关联?

更新:根据许多建议,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(); });

2 个答案:

答案 0 :(得分:3)

听起来你可能试图做的就是翻身&#34;删除&#34;对#34;其他人的责任&#34;所以你再也不用担心了。如果是这种情况,使用自定义删除工具的unique_ptr(不是shared_ptr)将有效:

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,包括建议std::unique_resource的{​​{3}}。

答案 1 :(得分:0)

如果你想要一个像lambda这样语义的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只是一个生成唯一变量名的宏,因此代码不会与手写声明冲突。

#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