简体   繁体   English

unique_ptr,自定义删除和零规则

[英]unique_ptr, custom deleter, and Rule of Zero

I am writing a class that uses two objects created using a C interface. 我正在编写一个使用C接口创建的两个对象的类。 The objects look like: 对象看起来像:

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

(similarly for bar_t ). (类似于bar_t )。 Because C++11, I want to wrap these in a smart pointer so I don't have to write any of the special methods. 因为C ++ 11,我想将它们包装在智能指针中,所以我不必编写任何特殊方法。 The class will have unique ownership of the two objects, so unique_ptr logically make sense... but I would still have to write a constructor: 该类将拥有这两个对象的唯一所有权,因此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));
};

On the flip side, with shared_ptr , I wouldn't have to write a constructor, or use a type alias, since I could just pass in delete_foo into reset() - although that would make my MyClass copyable and I don't want that. 另一方面,使用shared_ptr ,我不必编写构造函数,或者使用类型别名,因为我可以将delete_foo传递给reset() - 尽管这会使我的MyClass复制而我不希望这样。

What is the correct way to write MyClass using unique_ptr semantics and still adhere to Rule of Zero? 使用unique_ptr语义编写MyClass的正确方法是什么,仍然遵循Zero of Zero?

Your class doesn't need to declare a destructor (it will get the correct default implementation whether or not you declare it defaulted), so still obeys the "Rule of Zero". 您的类不需要声明析构函数(无论您是否声明默认实现,它都将获得正确的默认实现),因此仍然遵守“零规则”。

However, you might improve this by making the deleters function objects, rather than pointers: 但是,您可以通过使删除函数对象而不是指针来改进这一点:

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

This has a few benefits: 这有一些好处:

  • the unique_ptr doesn't need to store an extra pointer unique_ptr不需要存储额外的指针
  • the delete function can be called directly, rather than via a pointer 删除函数可以直接调用,而不是通过指针调用
  • you don't need to write a constructor; 你不需要写一个构造函数; the default constructor will do the right thing. 默认构造函数将做正确的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM