How to prevent delete px.get() for a unique

On the boost.org website, I saw an example of preventing delete px.get() for a shared_ptr (http://www.boost.org/doc/libs/1_51_0/libs/smart_ptr/sp_techniques.html#preventing_delete).

This is a good technique and I would like to apply this using std::unique_ptr in C++11, and after tooling around for a bit, I can't quite get their example working with std::unique_ptr.

Is it possible to prevent delete px.get() from being called on a std::unique_ptr?

Here is the code from the boost.org website showing how to prevent delete px.get from being called:

class X
{
private:

    ~X();

    class deleter;
    friend class deleter;

    class deleter
    {
    public:

        void operator()(X * p) { delete p; }
    };

public:

    static shared_ptr<X> create()
    {
        shared_ptr<X> px(new X, X::deleter());
        return px;
    }
};

The idea remains the same for unique_ptr also, except for the fact that the type of the deleter is part of the unique_ptr 's type.

#include <functional>
#include <memory>
#include <iostream>

using namespace std;

class X
{
private:

  ~X() {}

  class deleter
  {
  public:

    void operator()(X * p) { delete p; }
  };
  friend class deleter;

public:

  static shared_ptr<X> create_shared()
  {
    shared_ptr<X> px(new X, X::deleter());
    return px;
  }

  static unique_ptr<X, void(*)(X*)> create_unique()
  {
    return unique_ptr<X, void(*)(X*)>( new X, []( X *x ) { 
                                                  X::deleter()( x ); 
                                                } );
  }

  // If using VS2010
  static unique_ptr<X, std::function<void(X*)>> create_unique()
  {
    return unique_ptr<X, std::function<void(X*)>>( new X, X::deleter() );
  }
};

int main()
{
  auto x = X::create_shared();
  auto y = X::create_unique();
}

VS2010 does not implement implicit conversion of capture-less lambda to a function pointer, so the first create_unique will not work on it.


While calling delete px.get() is a pretty stupid thing to do, it's not usually something you try to prevent because it's not something you can easily do by accident. That said, here's how to fix this with unique_ptr, however it's ugly because the type of the deleter leaks into the type of the unique_ptr (why that is the case becomes clear when you look into the implementation details of unique_ptr vs. shared_ptr) and therefore the deleter has to be public, which means that the solution is not even waterproof because anybody can use the deleter. Unless you make the deleter's constructor private and make X a friend of it, however the question you also have to ask yourself is why bother? Somebody has to intentionally do the wrong thing by writing delete px.get() for it to become a problem.

class X
{
private:
   ~X() {}

public:
    struct deleter
    {
        void operator()(X * p) { delete p; }
    };

    static std::unique_ptr<X, deleter> create()
    {
      std::unique_ptr<X, deleter> px(new X, deleter());
      return px;
    }
};
链接地址: http://www.djcxy.com/p/64232.html

上一篇: 如何正确分离JavaScript视图/逻辑代码

下一篇: 如何防止删除px.get()的唯一