2015-01-15 110 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

相關問題