我的目标是实现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;
};
答案 0 :(得分:4)
您无法以编程方式检查指针值的获取方式。在您的情况下(这是真正编程的大部分内容!),解决方案是将您的接口记录到要求指针值可删除。您在用户上放置前提条件,这要求您的用户阅读文档并遵循它,您不能也不能提供用于验证这些前提条件的语言方法。您将负担转嫁给了您的用户。
这种先决条件负担总是形成一种“技术债务”,你想尽可能地避免它(但可能不以牺牲运行时成本为代价)。例如,在标准库中,我们强烈建议不要使用unique_ptr
的所有权构造函数,而应使用make_unique
来使用unique_ptr
,它没有先决条件并导致有效{{1}价值。这种设计是您在现实世界中管理技术债务的典范。
答案 1 :(得分:2)
不幸的是,你无能为力:对象的所有权必须转移到unique_ptr<T>
,如果你在全局,静态或自动区域使用对象的地址,这是不可能的。
标准库(即std::unique_ptr<T,Deleter>
)中的实现采用了删除参数,您可以使用该参数不删除任何内容。但是,这种用法非常值得怀疑,因为在这种情况下,您根本不需要unique_ptr
。