2015-01-15 222 views
7

它可以实现正是如此:为什么不std :: weak_ptr有operator->?

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的决定不具有操作符 - >?(他们一定想到了)

我可以想到潜在的原因,但我不知道官方原因是否存在。可能的原因是:

  • 劝阻的引用计数额外递增/递减的多个呼叫
  • 鼓励明确锁定,而不是(有些是隐藏的)异常

如果你感到困惑返回的shared_ptr的寿命,请参阅this paper.

另外,有人问为什么会使用weak_ptr,如果你预计它不会过期?答:循环。

回答

9

original proposalweak_ptr不包括operator->的超负荷。

我从没有看过每次会议的会议记录,但都遵循了讨论过的内容,并且不记得有人提议应该添加它。因此,它不存在的“官方”原因很可能在很大程度上是没有人提出将其加入。

如果你想回到非常开始,这个最约翰·埃利斯和大卫德特勒夫的Safe, Efficient Garbage Collection for C++纸,从Usenix的1994年。这包括在其附录B的weakptr型这是有所不同的茎(weakptr::pointer回报直接指向一个指针,或者如果指针已经被销毁,则是一个空指针),但是仍然没有使用操作符重载来完成这项工作。

Greg Colvin将original proposal to add counted_ptr写入标准。其counted_ptr基本上相当于现在称为shared_ptr,但不包括类似于weak_ptr的任何东西。

在委员会拒绝counted_ptr建议并通过auto_ptr代替之后不久,counted_ptr的基本概念在Boost上恢复。我不记得有任何关于增加一个operator->的讨论,但它在那里“长期居住”了很长时间,以至于完全有可能有人在我没有意识到的情况下提出它。

+2

但是据我所见,建议的'operator->'完全按照你的描述:转换为'shared_ptr',并且只允许在成功的情况下访问对象(否则抛出)。那是一件坏事? – 2015-01-15 18:39:53

+0

@MikeSeymour:你想保持shared_ptr并调用它的方法,而不必支付同步成本。 – 2015-01-15 18:42:27

+3

@AlexandreC .:有时你会这样做,在这种情况下手动转换仍然可用。有时您只想访问单个成员,在这种情况下,手动转换只是噪音,建议的操作员可以使其更加整洁。 – 2015-01-15 18:44:09

5

我会在给一个很好的理由采取了一枪,为什么这不是一个好主意:

有一点是清晰:

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

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

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

这就是说,用C++ 11,它太容易写:

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

明知ptrweak_ptr,意义和代码的行为是相当清楚的。

+0

在问及更多问题后,我认为你是对称的。如果operator->在缺乏最基本的运算符*时使weak_ptr看起来更像是一个实际的指针。 – Taylor 2015-01-16 17:48:49

+0

我也想到这是一个很好的理由。总之,weak_ptr不是一个指针,所以它不应该像一个行为。也许weak_ref会是更好的选择,但也可以使用术语参考。 – 2015-01-17 09:29:06

相关问题