除了 Mark Ransom 的答案之外, aunique_ptr<X, D>甚至可能不存储 a X*。
如果删除器定义了类型D::pointer,那么这就是存储的内容,并且可能不是真正的指针,它只需要满足NullablePointer要求并且(如果unique_ptr<X,D>::get()被调用)有一个operator*返回X&,但它不需要支持转换为其他类型。
unique_ptr非常灵活,不一定表现得非常像内置指针类型。
根据要求,这是一个存储类型不是指针的示例,因此无法进行强制转换。这有点做作,但在 C++ RAII 风格的 API 中包装了一个虚构的数据库 API(定义为 C 风格的 API)。OpaqueDbHandle 类型满足NullablePointer要求,但只存储一个整数,用作通过一些实现定义的映射查找实际 DB 连接的键。我并不是把它作为一个伟大设计的例子来展示,只是作为一个例子unique_ptr来管理一个不可复制的、可移动的资源,它不是一个动态分配的指针,其中“删除器”不只是调用一个析构函数和当unique_ptr超出范围时释放内存。
#include <memory>
// native database API
extern "C"
{
  struct Db;
  int db_query(Db*, const char*);
  Db* db_connect();
  void db_disconnect(Db*);
}
// wrapper API
class OpaqueDbHandle
{
public:
  explicit OpaqueDbHandle(int id) : id(id) { }
  OpaqueDbHandle(std::nullptr_t) { }
  OpaqueDbHandle() = default;
  OpaqueDbHandle(const OpaqueDbHandle&) = default;
  OpaqueDbHandle& operator=(const OpaqueDbHandle&) = default;
  OpaqueDbHandle& operator=(std::nullptr_t) { id = -1; return *this; }
  Db& operator*() const;
  explicit operator bool() const { return id > 0; }
  friend bool operator==(const OpaqueDbHandle& l, const OpaqueDbHandle& r)
  { return l.id == r.id; }
private:
  friend class DbDeleter;
  int id = -1;
};
inline bool operator!=(const OpaqueDbHandle& l, const OpaqueDbHandle& r)
{ return !(l == r); }
struct DbDeleter
{
  typedef OpaqueDbHandle pointer;
  void operator()(pointer p) const;
};
typedef std::unique_ptr<Db, DbDeleter> safe_db_handle;
safe_db_handle safe_connect();
int main()
{
  auto db_handle = safe_connect();
  (void) db_query(&*db_handle, "SHOW TABLES");
}
// defined in some shared library
namespace {
  std::map<int, Db*> connections;      // all active DB connections
  std::list<int> unused_connections;   // currently unused ones
  int next_id = 0;
  const unsigned cache_unused_threshold = 10;
}
Db& OpaqueDbHandle::operator*() const
{
   return connections[id];
}
safe_db_handle safe_connect()
{
  int id;
  if (!unused_connections.empty())
  {
    id = unused_connections.back();
    unused_connections.pop_back();
  }
  else
  {
    id = next_id++;
    connections[id] = db_connect();
  }
  return safe_db_handle( OpaqueDbHandle(id) );
}
void DbDeleter::operator()(DbDeleter::pointer p) const
{
  if (unused_connections.size() >= cache_unused_threshold)
  {
    db_disconnect(&*p);
    connections.erase(p.id);
  }
  else
    unused_connections.push_back(p.id);
}