2014-07-16 86 views
25

我感興趣如果這兩行代碼是一樣的:會發生什麼事時,使用make_shared

shared_ptr<int> sp(new int(1)); // double allocation? 
shared_ptr<int> sp(make_shared<int>(1)); // just one allocation? 

如果這是真的會有人請解釋爲什麼它僅在第二行一個分配?

+4

要說清楚的是,它不是'int'的雙重分配。它只是兩個單獨的分配:一個用於'int'對象,另一個用於'shared_ptr'控制塊。第二行只是一次性分配'int'和控制塊。 –

+2

請參見第2點:http://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/ – perreal

+1

在第二種情況下,'make_shared'分配'int'和控制塊,並且是因此可以一次性自由分配。在第一種情況下,你分配'int','shared_ptr'的構造函數分配控制塊,並且沒有辦法統一分配。 – nwp

回答

31

第一種情況不執行雙重分配,它執行兩個分配,一個用於管理對象,一個用於控制塊shared_ptr

對於第二種情況,cppreference有爲什麼std::make_shared通常只執行一個內存分配,它說一個很好的解釋(重點煤礦前進):

該功能通常分配內存於T對象和 shared_ptr的控制塊與單個內存分配(它是 標準中的非約束性要求)。相反,聲明 std :: shared_ptr p(new T(Args ...))執行至少兩個內存分配,這可能會產生不必要的開銷。

和從std::shared_ptr部,它說:創建

當shared_ptr的是通過調用的std :: make_shared或 的std :: allocate_shared中,兩者的控制塊存儲器中創建和 管理對象只有一個分配。管理對象 在控制塊的數據成員中就地構建。當 shared_ptr通過其中一個shared_ptr構造函數創建時,必須分別分配受管對象和控制塊。在這種情況下,控制塊存儲一個指向被管理對象的指針。

make_shared描述與C++11 draft standard它說,在部分20.7.2.2.6shared_ptr的創作一致

template<class T, class... Args> shared_ptr<T> make_shared(Args&&... args); 
template<class T, class A, class... Args> 
    shared_ptr<T> allocate_shared(const A& a, Args&&... args); 

[...]

備註:實現應該進行不超過一個內存 分配。 [注意:這提供了相當於 侵入式智能指針的效率。 - 注意]

[注意:這些函數通常會分配比 sizeof(T)更多的內存,以允許內部簿記結構,例如 引用計數。末端注]

香草薩特有在GotW #89 Solution: Smart Pointers使用make_shared的優勢,更詳細的解釋,並指出了一些優勢:

  • 它減少分配開銷
  • 它提高了局部性。
  • 避免顯式新增。
  • 避免異常安全問題。

請注意,當使用std::weak_ptrusing make_shared has some disadvantages

4
cppreference std::shared_ptr

說明在Implementation notes

在一個典型的實施方式中,標準:: shared_ptr的僅保持兩個指針:

  1. 的指針管理對象
  2. 一個指向控制塊

當調用shared_ptr時std :: make_shared或 std :: allocate_shared,控制塊和管理對象的內存都是使用單個分配創建的。管理對象 在控制塊的數據成員中就地構建。當 shared_ptr通過其中一個shared_ptr構造函數創建時,必須分別分配受管對象和控制塊。在這種情況下,控制塊存儲一個指向被管理對象的指針。

0

還有一個潛在的微妙的錯誤:在sp(new int)用你的拳頭分配一個int(其指針給sp),比SP本身分配一個控制塊(包含計數器和刪除器)。

現在,如果這樣做最後一次分配sp失敗(內存不足),您將剩下一個堆分配int,其指針不被任何人持有,因此無法刪除。 (內存泄漏)。