【问题标题】:Same address, multiple shared_ptr counters, is it forbidden by C++ standard?相同的地址,多个 shared_ptr 计数器,C++ 标准是否禁止?
【发布时间】:2012-07-29 10:32:32
【问题描述】:

假设我需要执行以下操作(这只是一些用于讨论 C++ 标准的富有想象力的代码,因此我不会讨论我为什么要这样设计它,所以不要用类似的东西来打扰我:你的设计是错误的。)

T* ptr = new T;
shared_ptr<T> p(ptr);
shared_ptr<T> q(ptr, SomeDeleterThatDoesnotDeleteButDoSomeOtherStuff());

假设逻辑保证p 或它的一些副本比q 的所有副本寿命更长,所以实际上不会有任何问题。我的问题是,它是否被 C++ 标准禁止,例如C++ 标准明确表示为 UB,不同的 shared_ptr 计数器共享相同的地址?

谢谢。

【问题讨论】:

  • 如果你return q;怎么办?
  • @Peter 我认为这就是想法——调用非删除器并在知道某些引用子集现在为空的情况下做一些有用的事情。
  • 就其目的而言,设计并没有那么那么糟糕。您可以通过将自定义删除器替换为 确实 删除并且还拥有自己的 shared_ptr 1. 到在其析构函数中执行操作的虚拟对象或 2. 具有另一个自定义删除器来保证正确销毁执行操作的删除器。但是,如果q 对象的集合相对于正确所有者p 的集合快速变化,那么这些方法的效率可能会降低。
  • @Potatoswatter,你明白了。这实际上正是我在实际工作中所做的:让非删除者拥有p
  • @icando 但是...当p 超出范围时,它将删除ptr,并且返回的q 将指向一个无效对象,无法得知。这似乎是一个非常糟糕的主意。你想达到什么目的?

标签: c++ c++11 shared-ptr language-lawyer


【解决方案1】:

如果第一个 shared_ptr 对象被销毁,那么您将获得 UB,因为使用第二个对象的对象可能会访问已释放的对象。

由于您确保第一个 shared_ptr 对象的寿命比第二个长,因此您不会获得 UB。

【讨论】:

    【解决方案2】:

    我在标准(嗯,最终草案)中找不到任何明确排除它的内容。我能找到的最接近的是20.9.11.2.10 shared_ptr casts中的注释

    5 [注:看似等价的表达式 shared_ptr(static_cast(r.get())) 最终会导致 未定义的行为,试图两次删除同一个对象。 -结尾 注意]

    这实际上似乎忘记了您使用自定义删除器的情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-07-08
      • 1970-01-01
      • 2012-03-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多