原始指针的 unique_ptr::reset 的等效实现?
Posted
技术标签:
【中文标题】原始指针的 unique_ptr::reset 的等效实现?【英文标题】:Equivalent implementation of unique_ptr::reset for raw pointers? 【发布时间】:2015-08-06 04:58:59 【问题描述】:我正在尝试将一段代码重构为单独的对象/文件。为了保持相同的行为,我的代码需要使用指向原始文件中关键组件的指针,它们被声明为 unique_ptrs。
我正在考虑提取原始指针并将它们传递给我的对象,因为我的部分不负责删除任何指针。 (我希望我正确理解所有权语义,对于 C++ 来说还是比较新的)。唯一需要注意的是我需要复制 unique_ptr::reset 的行为。这段代码会做同样的事情重置吗?
template <typename Type>
void reset(Type* ¤t_ptr)
Type* old_ptr = current_ptr;
current_ptr = new Type();
if(old_ptr != null)
delete old_ptr;
【问题讨论】:
不要将智能指针视为指针,而是将它们视为资源所有权。资源是否一次只有一个所有者,然后使用unique_ptr
;一个资源可以同时拥有多个所有者,然后使用shared_ptr
。另外,如果您从unique_ptr
获取原始指针,并且unique_ptr
对象超出范围并删除指向的内存,您认为会发生什么?这会让你在不知情的情况下得到一个过时的指针。
那......绝对不是reset()
所做的。你到底想复制什么?如果您的原始代码调用reset()
,则您正在删除指针。
如果您的部分不负责删除指针,那么您的部分将不想模拟std::unique_ptr::reset
,因为这会删除std::unique_ptr
正在管理的指针。只要您不删除/重新分配它们,使用原始指针是正确的做法。这应该是拥有智能指针的工作。
底线是你不能在不使用实际的std::unique_ptr
的情况下执行 reset()。您无法使用 std::unique_ptr
管理的 原始指针 来实现它。
感谢大家的回答。原始代码确实调用了reset
,我试图避免使用std::move
,这似乎很麻烦,因为它需要移动~15 个ptr,然后再放回去。
【参考方案1】:
如果您需要调用reset
,那么您实际上是在删除指针,并且在unique_ptr
的析构函数的上下文之外这样做会导致灾难(即使您的代码似乎可以工作,但可能仍然是未定义的行为)。
如果实际上您只需要取消引用(主要是 *
和 ->
)unique_ptr
,那么您应该在新代码中传递并使用对对象的 reference,使确保 unique_ptr
在您使用引用时不会死。
如果您需要重新分配或重置智能指针,您将需要一种替代方法,但您没有在问题中提供足够的信息来帮助确定这种替代方法的范围。
【讨论】:
【参考方案2】:不,reset()
不是这样做的。
正如 cmets 中所指出的,智能指针的特性是关于所有权,而不是指针本身。所有权意味着责任,因此如果unique_ptr
拥有一个对象,那么当unique_ptr
自己死亡时删除它是它的“工作”。 shared_ptr
稍微复杂一点,但它们也都是关于“在时机成熟时”删除对象,并从程序员身上卸下这个责任。
unique_ptr
s 是唯一的,也就是说,任何两个unique_ptr
s 都不应该拥有同一个对象。
现在,reset()
方法是一种表达方式:“嘿,unique_ptr
,我有一个新指针要你管理,所以销毁旧指针(如果你有的话)并获得它的所有权我要给你一个新的。从现在开始,这是你自己死后要毁掉的那个。”
这个操作对原始指针没有意义,因为它们不拥有任何所有权,也不会在正确的时间或类似的情况下杀死自己。
因此,与您的代码相比,相似之处在于确实删除了旧指针。但除了本质缺失(即原始指针不记得删除自己,不持有所有权)之外,普通的reset()
被赋予了一个指针,它并不会自己创建一个新对象。
【讨论】:
以上是关于原始指针的 unique_ptr::reset 的等效实现?的主要内容,如果未能解决你的问题,请参考以下文章