C++ 唯一\u ptr、自定义删除器和零规则

C++ 唯一\u ptr、自定义删除器和零规则,c++,c++11,rule-of-zero,C++,C++11,Rule Of Zero,我正在编写一个类,它使用两个使用C接口创建的对象。这些对象看起来像: typedef struct... foo_t; foo_t* create_foo(int, double, whatever ); void delete_foo(foo_t* ); (类似于条码)。因为C++11,我想把它们封装在一个智能指针中,所以我不必编写任何特殊的方法。该类将拥有这两个对象的唯一所有权,因此unique\u ptr在逻辑上有意义。。。但我仍然需要编写一个构造函数: template <typ

我正在编写一个类,它使用两个使用C接口创建的对象。这些对象看起来像:

typedef struct... foo_t;
foo_t* create_foo(int, double, whatever );
void delete_foo(foo_t* );
(类似于
条码
)。因为C++11,我想把它们封装在一个智能指针中,所以我不必编写任何特殊的方法。该类将拥有这两个对象的唯一所有权,因此
unique\u ptr
在逻辑上有意义。。。但我仍然需要编写一个构造函数:

template <typename T>
using unique_ptr_deleter = std::unique_ptr<T, void(*)(T*)>;

struct MyClass {
     unique_ptr_deleter<foo_t> foo_;
     unique_ptr_deleter<bar_t> bar_;

     MyClass()
         : foo_{nullptr, delete_foo}
         , bar_{nullptr, delete_bar}
     { }

     ~MyClass() = default;

     void create(int x, double y, whatever z) {
         foo_.reset(create_foo(x, y, z));
         bar_.reset(create_bar(x, y, z));
};
模板
使用unique_ptr_deleter=std::unique_ptr;
结构MyClass{
唯一的\u ptr\u deleter foo;
唯一的删除条;
MyClass()
:foo_u{nullptr,delete_foo}
,bar{nullptr,delete_bar}
{ }
~MyClass()=默认值;
创建空(整数x,双y,任意z){
重置(创建foo(x,y,z));
条重设(创建条(x,y,z));
};
另一方面,使用
shared\u ptr
,我不必编写构造函数或使用类型别名,因为我可以将
delete\u foo
传递到
reset()
——尽管这会使我的
MyClass
可复制,我不希望这样


使用
unique\ptr
语义编写
MyClass
并仍然遵守零规则的正确方法是什么?

您的类不需要声明析构函数(无论您是否声明它为默认值,它都将获得正确的默认实现),因此仍然遵守“零规则”

但是,您可以通过使deleters函数成为对象而不是指针来改进这一点:

template <typename T> struct deleter;
template <> struct deleter<foo_t> {
    void operator()(foo_t * foo){delete_foo(foo);}
};
template <> struct deleter<bar_t> {
    void operator()(bar_t * bar){delete_bar(bar);}
};

template <typename T>
using unique_ptr_deleter = std::unique_ptr<T, deleter<T>>;
模板结构删除器;
模板结构删除器{
void运算符()(foo_t*foo){delete_foo(foo);}
};
模板结构删除器{
void操作符()(bar_t*bar){delete_bar(bar);}
};
模板
使用unique_ptr_deleter=std::unique_ptr;
这有几个好处:

  • unique\u ptr
    不需要存储额外的指针
  • 可以直接调用delete函数,而不是通过指针
  • 您不需要编写构造函数;默认构造函数将做正确的事情

这看起来像是应该放在标准库中的东西。这太棒了。我最后做了一个小小的改动,使用了
模板结构unique\u ptr\u deleter;
,它有一个私有类
deleter
,然后
使用type=std::unique\u ptr;
。节省了必要的键入量……然后我可以将这两个n在一起(
unique\u ptr\u deleter\u t foo;