【问题标题】:Are weak pointers guaranteed to have expired by the time the std::shared_ptr deleter runs?弱指针是否保证在 std::shared_ptr 删除器运行时已经过期?
【发布时间】:2016-11-20 11:17:55
【问题描述】:

如果我有一个带有自定义删除器的std::shared_ptr<Foo>,是否可以保证所有关联的弱指针都被删除器视为过期? (如果您能引用标准中的相关部分,我将不胜感激。)

换句话说,下面的断言保证不会触发吗?

std::weak_ptr<Foo> weak;
std::shared_ptr<Foo> strong{
  new Foo,
  [&weak] (Foo* f) {
    assert(weak.expired());
    delete f;
  },
};

weak = strong;
strong.reset();

【问题讨论】:

  • 那么在调用删除器之前,使用计数器将为零,this expired reference 表示它“相当于use_count() == 0”。参考不权威,需要通过规范才能找到确定的答案(C++11、C++14、C++17标准的草案都是免费的,批准前的最后一个草案就好了够了)。
  • 同意。但标准的明确答案正是我所要求的。 :-) 我还没有找到适合自己的。
  • 我认为这是隐含的:如果您的断言不正确,那么您可以用weak.lock() 替换它(并且可能将所有权移出),然后共享对象的析构函数将是运行两次。
  • @KerrekSB:你怎么能“暗示”这样的事情?规范定义了行为,如果规范没有明确定义 this 的行为,那么它是未定义的。哦,我认为规范的 intent 很明显是在销毁对象之前递减计数器。但如果意图和措辞不一致,那就是缺陷。

标签: c++ c++11 c++14 shared-ptr


【解决方案1】:

标准没有任何保证。对于shared_ptr 的析构函数,规范只说:

  • 如果*this 为空或与另一个shared_ptr 实例共享所有权(use_count() > 1),则没有副作用。
  • 否则,如果*this 拥有对象p 和删除器d,则调用d(p)
  • 否则,*this 拥有指针 p,并调用 delete p

    [注意:由于*this 的销毁将与*this 共享所有权的实例数量减少1,在*this 被销毁后,与*this 共享所有权的所有shared_ptr 实例将报告@ 987654336@ 比之前的值小一。 ——尾注]

reset 的定义是将shared_ptr 交换为临时对象,然后将其销毁。

所以规范只保证use_count 的状态在析构函数完成后为零。未指定在该过程中将其设置为 0 的确切时间。

【讨论】:

  • 谢谢,这也是我对问题的理解,但你已经抓住了它的核心。 :-) 我想我将不得不依赖这样一个事实,即实现执行其他任何操作都是非常危险的(因为您可以将 std::shared_ptr&lt;Foo&gt; 恢复为当前正在被删除的对象)。
  • @jacobsa:你可以提交一份缺陷报告。他们可能会修复 C++17 的措辞。
  • 谢谢,我已经提交了缺陷报告。
【解决方案2】:

C++14 标准中显然没有任何东西可以保证这一点。我现在打开了一个defect report 用于解决问题的标准。

【讨论】:

  • 您的缺陷报告已更新。他们似乎认为这不是一个缺陷:删除者不应该对这些事情进行探索,并且允许它的实现负担显然比他们想要修复它要多。
  • 是的,我看到了。老实说,我不明白他们所指的实施负担是什么。
猜你喜欢
  • 1970-01-01
  • 2021-07-23
  • 2020-06-09
  • 1970-01-01
  • 2012-09-27
  • 2016-01-03
  • 2011-06-27
  • 1970-01-01
相关资源
最近更新 更多