【问题标题】:How to forward declare custom unique_ptr如何转发声明自定义 unique_ptr
【发布时间】:2015-11-04 13:49:00
【问题描述】:

我在实现如下构造时遇到问题。这个想法是我在一些头文件中定义了一个实用程序函数,它分配了某种资源。为了让客户不必自己释放它,我想把它包装成一个智能指针。 不幸的是,我不得不以某种方式将删除器类型传递给客户端,并且无法正确地向前声明它。我当前的解决方案看起来像这样,导致多个定义错误,因为删除器是使用实用程序的每个附加包含重新定义的。h

我正在寻找哪种优雅的解决方案?

// utilities.h
namespace foo
{
  auto del = []( MyResource* res) { Deallocate( res ); };
  std::unique_ptr<MyResource, decltype(del)> getResource( );
}

// utilities.cpp
namespace foo
{
  std::unique_ptr<MyResource, decltype(foo::del)> getResource( )
  {
    return std::unique_ptr<MyResource, decltype(foo::del)>( Allocate( ), del );
  }
}

【问题讨论】:

  • 将删除器设为函数而不是lambda-object变量,并将函数标记为inline?
  • @JoachimPileborg 这应该是一个答案。 OTOH,它可以防止默认构造这样的unique_ptr

标签: c++ unique-ptr forward-declaration


【解决方案1】:

使用普通类而不是 lambda:

标题:

namespace foo {

  struct Deleter {
    void operator() (MyResource *res) const { Deallocate(res); }
  };

  std::unique_ptr<MyResource, Deleter> getResource();
}

来源:

namespace foo
{
  std::unique_ptr<MyResource, decltype(foo::del)> getResource( )
  {
    return std::unique_ptr<MyResource, Deleter>( Allocate( ) );
  }
}

这还有一个额外的好处,那就是在创建指针时不必指定删除器——默认构造的Deleter 就可以了。

【讨论】:

  • 是的,你的方式更好
【解决方案2】:

我推荐Angew's answer 主要是因为std::function 中类型擦除的额外开销。不过知道这种方式也有可能是不好的。


修复很简单:在标头中有声明,在源中有定义:

// utilities.h
namespace foo {
  using del_t = std::function<void(MyResource *)>;
  extern  del_t del;
  std::unique_ptr<MyResource, del_t> getResource();
}

// utilities.cpp
namespace foo {
  del = [](MyResource* res) {
      Deallocate(res);
  };
  std::unique_ptr<MyResource, del_t> getResource() {
      return std::unique_ptr<MyResource, del_t>(Allocate(), del);
  }
}

【讨论】:

  • 这会带来std::function中类型擦除的额外开销。
  • @Angew 是的。不知道任何其他方式来指定 lambda 的类型。如果这是一个问题,他应该去一个简单的功能。
猜你喜欢
  • 1970-01-01
  • 2014-11-09
  • 2020-02-10
  • 2020-01-07
  • 2019-02-26
  • 1970-01-01
  • 2021-09-12
  • 2019-07-02
  • 1970-01-01
相关资源
最近更新 更多