2017-05-03 126 views
6

假設我們有一個函數期望按值分享指針。 (在實際生活中的例子我把它由右值參考,並將其轉發到一個成員。)std :: move into static_pointer_cast:爲什麼static_pointer_cast沒有右值引用超載?

void f(std::shared_ptr<Derived> ptr) { ... } 

但我們只具有共用的指針的基類,所以我們使用static_pointer_cast

std::shared_ptr<Base> ptr = std::make_shared<Derived>(); 
f(std::static_pointer_cast<Derived>(ptr)); 

第一次賦值(從臨時構造ptr)是否觸發引用計數的原子增量和減量,或者共享指針是否被移動? (請注意,它正在上傳。)

static_pointer_cast內有一個引用計數的原子增量。如果我們不再需要ptr,我們希望將它移動到f。但是,因爲有服用右值引用沒有static_pointer_cast過載,此舉將不會有任何效果:

f(std::static_pointer_cast<Derived>(std::move(ptr))); 

我們還是儘快ptr被破壞有單位遞增和相應的原子遞減。爲什麼沒有這種超載?

+2

推測:這裏列出的「可能的實現」:http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast都使用'shared_ptr'的構造函數,它不接受移動的參數。現在爲什麼*沒有我無法告訴你的移動變化。 – vu1p3n0x

+0

你不能移動static_pointer_cast的結果嗎? – rubenvb

+1

@rubenvb static_pointer_cast的結果是臨時的,因此是一個右值,所以它會自動移動。但問題是你顯然無法進入static_pointer_cast。 – Creep4Play

回答

3

我可以回答你的問題的第一部分,但不是第二部分。雖然我不知道是否它是由標準的規定,我敢肯定:

std::shared_ptr<Base> ptr = std::make_shared<Derived>(); 

不會做任何多餘的refcounter遞增/遞減。首先,讓我觀察一下,這實際上不是一項任務,而是ptr的構建。顯然它是由臨時構建的,顯然臨時是不同類型的。將要匹配的構造方法的簽名是(http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr):

template< class Y > 
shared_ptr(shared_ptr<Y>&& r); 

在它說的注意事項:

布展構建從r一個shared_ptr。構建完成後,*包含r的前一個狀態的副本,r爲空,其存儲的指針爲空。模板超載不參與重載如果Y *不能隱式轉換到T *

在這種情況下,YDerivedTBase,所以我們顯然得到隱式轉換從Y*T*,所以構造函數是合法的。嚴格地說,它可能符合允許引用計數首先上升到2,然後再降回到1.但顯然這違背了移動構造函數的整個目的,所以我非常懷疑這是如何實現的。

相關問題