Where's the proper (resource handling) Rule of Zero? [closed]

|▌冷眼眸甩不掉的悲伤 提交于 2019-11-29 09:29:25

Background: Rule Of Zero

First and foremost, that article is about a much more general idea than just a the resource handle wrapper example it mentions.

The point is that whenever a class contains members with 'non-trivial' ownership semantics, the class should not be responsible for the mechanics of ensuring proper value semantics (copy. assign, move, destruct) of the containing class. Rather, each constituent should itself implement 'Rule-Of-3+' as appropriate, so that the composite class can leverage the compiler-defaulted special members.

Further more, the new standard smart pointer types greatly simplify the task of making this happen for the contained types. In most cases the members that required attention would be pointers: std::unique_ptr, shared_ptr, weak_ptr address the needs here.

For custom resource types you might have to write a Rule-Of-3+ wrapper class, but only once. And the rest of your classes will benefit from the Rule-Of-Zero.


The bullets:

  • One is able to peer and use the base type the #define (or typedef) HANDLE is built upon. For me this should be hidden knowledge, and a solution be based exclusively on what the interface makes available, HANDLE.

A: 90% of the time you can (and should) use std::unique_ptr<> with a custom deleter. The knowledge and responsibility for cleanup are still with the allocator. The way it should.

In the remaining cases, you'll have to write a single wrapper class for your specific resource that isn't otherwise supported.

  • Handles, can be anything, they're not required to be pointer types.

They can. You'd look at e.g. boost::optional. Or write that wrapper. The point is, you want it isolated for the resource. You don't want to complicate a class that happens to own/contain such a resource.

Is this handle focused RAII wrapper already done and usable in some cool library?

For your case, it's called unique_ptr. Observe:

struct WndLibDeleter
{
  typedef HANDLE pointer;

  void operator()(HANDLE h) {::FreeLibrary(h);}
};

using WndLibrary = std::unique_ptr<HANDLE, WndLibDeleter>;

WndLibrary LoadWndLibrary(std::wstring const& name)
{
  return WndLibrary(::LoadLibrary(name.c_str()));
}

With deleters, unique_ptr can service store and service any kind of object that is NullablePointer. HANDLE is a NullablePointer, so you can service it.

For objects that aren't NullablePointers, you'll have to use something else. The point of the Rule of Zero is to make "something else" as small as possible. It would be nothing more than a RAII-wrapper around the type, providing nothing more than access to it and move support. Therefore, the vast majority of your code does not need explicit copy/move constructors; just those few leaf classes.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!