我感興趣如果這兩行代碼是一樣的:會發生什麼事時,使用make_shared
shared_ptr<int> sp(new int(1)); // double allocation?
shared_ptr<int> sp(make_shared<int>(1)); // just one allocation?
如果這是真的會有人請解釋爲什麼它僅在第二行一個分配?
我感興趣如果這兩行代碼是一樣的:會發生什麼事時,使用make_shared
shared_ptr<int> sp(new int(1)); // double allocation?
shared_ptr<int> sp(make_shared<int>(1)); // just one allocation?
如果這是真的會有人請解釋爲什麼它僅在第二行一個分配?
第一種情況不執行雙重分配,它執行兩個分配,一個用於管理對象,一個用於控制塊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.6
shared_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。
說明在Implementation notes
部
在一個典型的實施方式中,標準:: shared_ptr的僅保持兩個指針:
- 的指針管理對象
- 一個指向控制塊
當調用shared_ptr時std :: make_shared或 std :: allocate_shared,控制塊和管理對象的內存都是使用單個分配創建的。管理對象 在控制塊的數據成員中就地構建。當 shared_ptr通過其中一個shared_ptr構造函數創建時,必須分別分配受管對象和控制塊。在這種情況下,控制塊存儲一個指向被管理對象的指針。
還有一個潛在的微妙的錯誤:在sp(new int)
用你的拳頭分配一個int(其指針給sp
),比SP本身分配一個控制塊(包含計數器和刪除器)。
現在,如果這樣做最後一次分配sp
失敗(內存不足),您將剩下一個堆分配int,其指針不被任何人持有,因此無法刪除。 (內存泄漏)。
要說清楚的是,它不是'int'的雙重分配。它只是兩個單獨的分配:一個用於'int'對象,另一個用於'shared_ptr'控制塊。第二行只是一次性分配'int'和控制塊。 –
請參見第2點:http://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/ – perreal
在第二種情況下,'make_shared'分配'int'和控制塊,並且是因此可以一次性自由分配。在第一種情況下,你分配'int','shared_ptr'的構造函數分配控制塊,並且沒有辦法統一分配。 – nwp