std::make_shared
是 C++ 標準庫中的一個函數模板,用于簡化智能指針 std::shared_ptr
的創建過程。引入 std::make_shared
的主要原因是提高代碼的安全性、性能和可讀性。以下是詳細分析:
1. 安全性提升
避免顯式調用 new
導致的錯誤
在不使用 std::make_shared
的情況下,我們通常手動調用 new
來分配內存并初始化對象:
std::shared_ptr<MyClass> ptr(new MyClass(arg1, arg2));
這種方式容易引發以下問題:
- 異常安全問題:如果在
new
和std::shared_ptr
構造之間拋出異常,會導致資源泄漏。 - 內存管理錯誤:手動調用
new
容易忘記釋放資源。
使用 std::make_shared
后,這些問題都被封裝到函數內部,減少了手動操作的可能性:
auto ptr = std::make_shared<MyClass>(arg1, arg2);
避免顯式分配內存導致的錯誤
std::make_shared
內部會同時完成內存分配和對象構造,確保兩者是一致的。而直接使用 std::shared_ptr(new T)
可能會出現分配內存失敗但對象已經構造完成的情況,從而導致內存泄漏。
2. 性能優化
減少一次內存分配
普通方式創建 std::shared_ptr
時,通常需要兩次內存分配:
- 分配一塊內存存儲
std::shared_ptr
的控制塊(包含引用計數等元信息)。 - 分配另一塊內存存儲實際的對象。
而 std::make_shared
將這兩塊內存合并成一次分配,提高了內存分配效率。這尤其在頻繁創建對象時會有顯著的性能提升。
緩存局部性
由于 std::make_shared
將控制塊和對象存儲在一起,訪問控制塊時的緩存命中率更高,從而提升了程序的整體性能。
3. 提高代碼可讀性和簡潔性
使用 std::make_shared
可以使代碼更加簡潔和直觀:
// 普通方式
std::shared_ptr<MyClass> ptr(new MyClass(arg1, arg2));// 使用 make_shared
auto ptr = std::make_shared<MyClass>(arg1, arg2);
后者不僅減少了代碼量,還避免了重復書寫 new
,使代碼更易于閱讀和維護。
4. 示例對比
普通方式
std::shared_ptr<int> ptr(new int(42)); // 顯式調用 new
*ptr = 10; // 修改對象
使用 make_shared
auto ptr = std::make_shared<int>(42); // 自動分配和構造
*ptr = 10; // 修改對象
可以看到,std::make_shared
的語法更加簡潔且不易出錯。
5. 總結
std::make_shared
的優點包括:
- 提高安全性(避免資源泄漏和異常問題)。
- 提高性能(減少內存分配次數,提高緩存命中率)。
- 提高代碼可讀性和簡潔性。
因此,在現代 C++ 編程中,推薦優先使用 std::make_shared
來創建 std::shared_ptr
。
參考資料
- C++ Reference: std::make_shared
- Effective Modern C++: Item 14