2015-03-13 95 views
7

我在写一个使用两个使用C接口创建的对象的类。对象看起来像:unique_ptr,自定义删除器和零规则

typedef struct... foo_t; 
foo_t* create_foo(int, double, whatever); 
void delete_foo(foo_t*); 

(类似地为bar_t)。因为C++ 11,我想把它们包装在一个智能指针中,所以我不必编写任何特殊的方法。本课程将有两个对象的唯一所有权,所以unique_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)); 
}; 

在另一面,与shared_ptr,我就不会去写一个构造函数,或者使用类型别名,因为我可以将delete_foo传递到reset()--尽管这会使我的MyClass可复制,我不想那样做。

使用unique_ptr语义编写MyClass的正确方法是什么并仍然遵循零规则?

回答

8

你的类不需要声明一个析构函数(它会得到正确的默认实现,不管你是否声明它是默认的),所以仍然服从“零规则”。

但是,您可能通过使删除器函数对象改善这一点,而不是指针:

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>>; 

这有几个好处:

  • unique_ptr并不需要存储额外的指针
  • 删除功能可以直接调用,而不是通过指针
  • 你不需要写一个构造函数;默认的构造函数会做正确的事情。
+0

这看起来应该是标准库中的东西。 – rubenvb 2015-03-13 16:26:23

+1

这很棒。我用'template struct unique_ptr_deleter;'有一个私人类'deleter',然后'使用type = std :: unique_ptr ;'。节省必要的输入量...然后我可以将它们放在一起('unique_ptr_deleter_t foo_;') – Barry 2015-03-13 17:28:39