为什么std :: weak_ptr没有operator->?

时间:2015-01-15 18:24:15

标签: c++ shared-ptr smart-pointers weak-ptr

可以这样实施:

  std::shared_ptr<T> operator->() {
      auto shared = lock();
      if(shared == nullptr) {
          throw std::bad_weak_ptr(); // or some other exception
      }
      return shared;
  }

Live Demo

为什么weak_ptr的作者决定不拥有operator-&gt;?(他们必须想到它)

我可以想到潜在的原因,但我想知道官方原因是什么,如果存在的话。可能的原因:

  • 不鼓励多次呼叫的额外增加/减少引用次数
  • 鼓励显式锁定而不是(有些隐藏)异常

如果您对返回的shared_ptr的生命周期感到困惑,请参阅this paper.

另外,有人问为什么如果你期望它没有过期,会使用weak_ptr?答案:周期。

2 个答案:

答案 0 :(得分:9)

original proposal weak_ptr未包含operator->的重载。

我从未查看过每次会议的会议记录,但是已经按照所讨论的内容进行了讨论,并且不记得有人提到应该添加它。因此,它不存在的“官方”原因很可能是没有人提议将其添加。

如果你想回到非常的开头,大部分内容都来自John Ellis和David Detlef的Safe, Efficient Garbage Collection for C++论文,来自Usenix 1994.其中包括weakptr在附录B中键入。这有点不同(weakptr::pointer直接返回一个指针,如果指针已被销毁,则返回空指针),但仍然没有使用运算符重载来完成这项工作。

Greg Colvin写了original proposal to add counted_ptr标准。其counted_ptr基本上与现在称为shared_ptr的内容相同,但不包含与weak_ptr类似的任何内容。

在委员会拒绝counted_ptr提案并采用auto_ptr之后不久,counted_ptr的基本想法在Boost上得以恢复。我不记得有任何关于添加operator->的讨论,但它在那里“活了”很长时间以至于完全有可能有人在没有意识到它的情况下提出它。

答案 1 :(得分:6)

我会尽力说明为什么这不是一个好主意:

有一点是清晰度:

ptr->foo();
ptr->bar();

这里的问题是在第一次和第二次调用之间的某个地方,ptr可能会通过一个不同的线程(这将是一个竞争条件)或者通过调用foo的副作用而到期。

另一件事是对称:当我有一个指针时,我期望运算符*->和隐式转换为布尔值。有些人可能不同意,但运营商*->经常重合。我很惊讶这不是这种情况。

也就是说,使用C ++ 11,它写起来太容易了:

if (auto p = ptr.lock()) {
    p->foo();
    p->bar();
}

知道ptrweak_ptr,该代码的含义和行为非常明确。