2014-10-09 35 views
0

許多程序員主張使用make_shared,因爲它減少了鍵入操作並減少了編程錯誤。然而,在某些情況下,使用shared_ptr的構造函數是不可避免的。其中一種情況是當您有一個現有指針時,您想要shared_ptr擁有,因爲shared_ptr<Foo>(&existing_ptr)是錯誤的代碼。相反,你必須使用笨拙的shared_ptr<Foo>(shared_ptr<Foo>(), p)。你不僅要重複自己,還必須創建一個臨時對象。更簡單的方法讓shared_ptr擁有一個現有的指針

int main() 
{ 
    using namespace std; 

    Foo foo; 
    foo.n = 1; 
    { 
     auto ptr = make_shared<Foo>(move(foo)); 
     ptr->n = 42; 
     cout << ptr->n << " " << foo.n << '\n'; 
    } 
    { 
     auto p = &foo; 
     auto ptr = shared_ptr<Foo>(shared_ptr<Foo>(), p); 
     ptr->n = 42; 
     cout << ptr->n << " " << foo.n << '\n'; 
    } 

    return 0; 
} 
Foo::Foo() 
Foo::Foo(Foo &&) 
42 1 
Foo::~Foo() 
42 42 
Foo::~Foo() 

什麼是有shared_ptr自己現有的指針更簡潔的方式?

+2

'&existing_ptr'顯然是錯的 - 你的意思是'&existing_object'。 – Yakk 2014-10-09 19:29:58

+1

'shared_ptr (&existing_ptr)'只是不正確的,但'shared_ptr (existing_ptr)'有什麼錯誤? – 2014-10-09 19:37:08

+1

@ n.m。在這種情況下''shared_ptr'會嘗試刪除銷燬指針,這將失敗,因爲指針不指向分配'new'的對象。 – 2014-10-09 19:43:13

回答

2

IMO你在那裏做什麼不應該很容易,因爲這是非常危險的,只有在高度專業化的環境下輸入一個類名稱兩次應該是你最小的擔心。

但在這裏是通過使用虛擬刪除器來實現同樣的事情稍微簡潔的方式:

auto ptr = std::shared_ptr<Foo>(&foo, [](void*){}); 

而且,你的做法是不是真的正確地說,ptr擁有foo;而是它擁有空對象std::shared_ptr<Foo>指向foo(有關更長的討論,請參閱this answer)。在我上面的代碼中,它在某種技術意義上「擁有」foo(或者至少它認爲它確實);當它的引用計數達到零時,它就被阻止對它做任何事情。

6

該構造函數的預期用途是允許共享指針指向共享指針的子對象。

您的使用不是預期的用途,而且非常危險,因爲您隱式地創建了一個保證,即傳遞給共享指針的數據將持續與共享指針或其副本一樣長的時間,然後失敗在任何有意義的意義上執行這一保證。

如果您將共享指針傳遞給某個函數,那麼它在15分鐘後有權緩存該副本並使用它。如果你沒有向一個函數傳遞一個共享指針,你不需要一個。

一般來說,如果一個函數打算以難以預測的方式延長參數的生命週期,那麼它只需要一個共享指針。所以,如果你有一個函數需要一個共享指針,並且永遠不會延長它的生命週期(或者指向它的指針的生存期),它就不應該採用共享指針。問題出在你打電話的功能上,而不是你如何通過箍環來打電話。

只有當你都有一個功能即碎,無法修復上自由存儲區進行的Foo副本是過於昂貴,是你的技術值得嘗試。無論如何,這應該是極端的角落案例。

+0

我同意,也沒有太多的意義 – 2014-10-09 19:45:14

相關問題