【问题标题】:Implementing unique_ptr: Deleting non-allocated objects实现 unique_ptr:删除未分配的对象
【发布时间】:2017-04-09 22:59:35
【问题描述】:

我的目标是实现一个简单版本的 unique_ptr,它只提供构造函数、析构函数、->、* 和 release()。

但是,我不知道在使用未分配指针初始化 unique_ptr 的情况下该怎么办。

例如

int i = 0;
unique_ptr<int> p{&i};

如果 unique_ptr 只是在它拥有的指针上调用 delete,这将产生未定义的(和不希望的)行为,至少据我所知。我能做些什么来防止这种情况发生?

编辑:我对这个问题的尝试如下......

template<typename T>
class Uptr
{
public:
    Uptr<T>(T* pt) : mp_owned{pt} {}
    ~Uptr<T>() {delete mp_owned;}

    Uptr<T>(const Uptr<T>&) = delete;
    Uptr<T>& operator=(const Uptr<T>&) = delete;

    T& operator*() const {return *mp_owned;}
    T* operator->() const {return mp_owned;}

    T* release() {return mp_owned;}

private:
    T* mp_owned;
};

【问题讨论】:

  • real unique_ptr 也是如此。但是要回答你的具体问题 - 你不能做任何事情,可靠/便携(至少不是我上次熟悉 C++)。
  • 你可以有一个标志来控制你是否调用 delete,并在堆栈分配的对象上创建 unique_ptr 时设置它。它当然会问为什么你首先要创建 unique_ptrs 来堆叠分配的对象
  • 这没有意义。 unique_ptr 的意义在于它是资源的唯一所有者。如果stack 拥有它,那么unique_ptr 不应指向它。
  • @Galik “没有意义”不是不彻底的借口。

标签: c++ pointers unique-ptr


【解决方案1】:

您无法以编程方式检查指针值是如何获得的。在您的情况下(这是实际编程的大部分内容的高度代表!),解决方案是记录您的界面要求指针值是可删除的。您为您的用户设置了一个前提条件,这要求您的用户阅读文档并遵循它,而您没有也不能提供验证这些前提条件的语言方法。您将负担转嫁给您的用户。

这样的前置条件负担总是形成一种“技术债务”,您希望尽可能地避免它(但也许不以牺牲运行时成本为代价)。例如,在标准库中,我们强烈反对使用unique_ptr 的所有权获取构造函数,而是作为用户使用make_unique,它没有先决条件并导致有效的unique_ptr 值。这种设计是您在现实世界中如何管理技术债务的典范。

【讨论】:

    【解决方案2】:

    很遗憾,对此您无能为力:必须将对象的所有权转移到unique_ptr&lt;T&gt;,如果您在全局、静态或自动区域中使用对象的地址,这是不可能的。

    标准库中的实现,即std::unique_ptr&lt;T,Deleter&gt;,采用删除器参数,您可以使用它删除任何内容。然而,这种用法是非常值得怀疑的,因为在这种情况下你根本不需要unique_ptr

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-12-28
      • 2019-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多