【问题标题】:std::unique_ptr::reset checks for managed pointer nullity?std::unique_ptr::reset 检查托管指针是否为空?
【发布时间】:2014-02-06 14:48:36
【问题描述】:

我一直在阅读有关 C++11 智能指针的信息,以便在我的源代码中使用它们,我一直在阅读的文档是 cppreference.com 上的文档;在阅读std::unique_ptr 时,reset function 上有一个对我来说似乎不正确的文档(强调我的):

替换托管对象。

  • 给定current_ptr,由*this 管理的指针按以下顺序执行以下操作:

    1. 保存当前指针old_ptr = current_ptr的副本。
    2. 用参数current_ptr = ptr 覆盖当前指针。
    3. 如果旧指针非空,则删除之前管理的对象if(old_ptr != nullptr) get_deleter()(old_ptr)

在 C++ 标准文档中,我们可以阅读众所周知的删除空指针功能:

n3690标准中提取5.3.5删除(强调我的):

如果delete-expression的操作数的值不是空指针值,那么:

——如果对要删除的对象的新表达式的分配调用没有省略,delete-expression 将调用一个释放函数。从 new-expression 的分配调用返回的值应作为第一个参数传递给释放函数。

否则,delete-expression不会调用释放函数

所以,我想知道为什么 cppreference 说 unique_ptr::reset 函数在删除托管指针之前检查它的空值,即使标准说不会通过空指针调用释放函数(这就是 cppreference文档对我来说似乎不正确)。

很明显,我一定是弄错了,这样做肯定是有原因的,但我无法想象这可能是什么原因。有什么提示吗?

PS:标准中的哪里定义了std::unique_ptr 必须如何实现或表现?在 20.9.1 类模板 unique_ptr 中,我找不到任何关于 check-for-nullity 的内容。

【问题讨论】:

  • delete 并不是摆脱类指针资源的唯一方法。你可以有一个自定义删除器frees 或做其他不喜欢空指针的事情。

标签: c++ c++11 language-lawyer unique-ptr delete-operator


【解决方案1】:

是的,标准要求检查非空值(C++11,[unique.ptr.single.modifiers]§4):

void reset(pointer p = pointer()) noexcept;

4 效果:p 分配给存储的指针,然后如果存储的指针的旧值old_p 不等于nullptr,则调用@ 987654326@。 [ 注意: 这些操作的顺序很重要,因为对 get_deleter() 的调用可能会破坏 *this——尾注 ]

(强调我的)

讨论:另一种标准化的方法是将“负担”放在类的用户身上,即要求所有删除器(默认一个任何自定义的)在空指针上调用时可以正常工作。

但是,我理解这个想法是启用像 free() 这样的函数,甚至像假设的 unlock_mutex(Mutex*) 这样的东西,作为开箱即用的删除器,无论它们如何/是否处理空指针。所以把这个检查放到unique_ptr本身就拓宽了可以直接使用的删除器的选择范围。

【讨论】:

  • 如果删除空指针没有任何效果,那么这样做的原因是什么?
  • @PaperBirdMaster 如果删除器不是默认删除器,并且不能使用空指针怎么办?
  • 好吧,我假设如果您创建自定义删除器,该自定义删除器必须符合一些条件,例如 不要尝试对空指针进行操作 i>,但显然,这是我的错误(而且我找不到关于自定义删除器的条件/先决条件,所以这一定是原因:)
  • @PaperBirdMaster 是的,这将是标准采用的替代途径。但我理解这个想法是启用像free() 这样的功能,甚至像假设的unlock_mutex(Mutex*) 这样的功能作为开箱即用的删除器,所以他们决定把负担放在unique_ptr 而不是它的用户身上。
  • 最后一条评论很好,您介意将此解释包含在未来读者的答案中吗? (即使在那之后我已经接受了答案)
【解决方案2】:

如果您的删除器不执行简单的删除操作怎么办?如果您的 unique_ptr 有一个执行其他操作的自定义删除器怎么办,您是否希望使用 nullptr 作为参数调用您的删除器? :D

【讨论】:

  • 如果我想允许使用空指针调用我的自定义删除器:我将检查删除器本身的无效性;P 但现在我可以假设我的自定义删除器不会被调用nullptr(即使我想这样做,出于某种随机和奇怪的原因)
  • @PaperBirdMaster 实际上,检查空指针的delete 运算符是一种语言中的怪人,在这种语言中,您不应该为不使用的东西付费(为什么我要付费额外检查我是否从不删除nullptr?),但我猜是出于历史原因并模仿free() 的行为,它是为了检查nullptr,因为足够多的编码人员似乎依赖这种行为。您使用的相同自定义删除器也可以在另一个上下文中使用,其中检查 nullptr 没有多大意义,只需要一个包装器来进行空检查会很遗憾:)
猜你喜欢
  • 1970-01-01
  • 2020-11-09
  • 1970-01-01
  • 1970-01-01
  • 2021-07-02
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
  • 2015-04-14
相关资源
最近更新 更多