yohhoyの日記

技術的メモをしていきたい日記

nullptrを所有するshared_ptr

C++11標準ライブラリのstd::shared_ptrでは、ヌルポインタを所有することが可能となっている。

デフォルトコンストラクトされたshared_ptrオブジェクトは空(empty)となる。一方、明示的にnullptrを与えてコンストラクトしたshared_ptrオブジェクトは “ヌルポインタを所有(own)する” *1。この場合はshared_ptrオブジェクト破棄時にカスタムデリータが呼ばれる。

#include <memory>
#include <iostream>

int main()
{
  auto custom_deleter = [](void* p){
    assert(p == nullptr);
    std::cout << "deleter called" << std::endl;
  };

  std::shared_ptr<void> sp(nullptr, custom_deleter);
}  // 標準出力に"deleter called"が出力される

N3337 20.7.2.2/p1, 20.7.2.2.1/p1-2,9-10, 20.7.2.2.2/p1より部分引用。

(snip) A shared_ptr object is empty if it does not own a pointer.

constexpr shared_ptr() noexcept;
1 Effects: Constructs an empty shared_ptr object.
2 Postconditions: use_count() == 0 && get() == 0.

template <class Y, class D> shared_ptr(Y* p, D d);
template <class D> shared_ptr(nullptr_t p, D d);

9 Effects: Constructs a shared_ptr object that owns the object p and the deleter d. (snip)
10 Postconditions: use_count() == 1 && get() == p.

~shared_ptr();
1 Effects:

  • If *this is empty or shares ownership with another shared_ptr instance (use_count() > 1), there are no side effects.
  • Otherwise, if *this owns an object p and a deleter d, d(p) is called.
  • Otherwise, *this owns a pointer p, and delete p is called.

追記:"empty" の定義が曖昧?

[twitter:@k_satoda]さんからの指摘を受けて。

N3337 20.7.2.2/p1は "A shared_ptr object is empty if it does not own an object a pointer." とすべきかも。


関連URL

*1:ヌルポインタ定数として NULL や 0 を指定した場合も同様の動作となる。