std::make_shared比直接使用new配合std::shared_ptr更高效,因为它通过一次内存分配同时创建对象和控制块,减少开销、提升缓存局部性并增强异常安全;而new方式需两次分配,性能较低且存在异常安全隐患;但当需要自定义删除器、构造函数非公开或存在weak_ptr长期持有场景时,只能或应慎用std::make_shared,此时可选择new方式以获得更大灵活性,总结:常规场景优先使用std::make_shared,特殊需求下退回到new并注意资源管理问题。

std::make_shared
new
std::shared_ptr
当你使用
new
std::shared_ptr
std::shared_ptr<Foo> ptr(new Foo());
这会执行 两次独立的内存分配:
new Foo()
std::shared_ptr
而使用
std::make_shared
auto ptr = std::make_shared<Foo>();
它会 一次性分配一块连续内存,同时包含:
这种优化称为 内存共置(allocation elision) 或 合并分配(combined allocation)。
std::make_shared
减少内存分配次数:从两次变为一次,显著降低动态内存分配的开销(
malloc
free
提高缓存局部性:对象和控制块在内存中相邻,访问时更可能命中同一缓存行,提升性能。
更快的构造速度:由于只做一次分配,且内部使用完美转发构造对象,效率更高。
异常安全更好:考虑如下代码:
// 潜在问题:如果 make_shared 之前抛异常,可能造成资源泄漏 functionThatTakesSharedPtr(std::shared_ptr<Foo>(new Foo), expensiveCall());
参数求值顺序未定义,
new Foo
expensiveCall()
expensiveCall()
new Foo
shared_ptr
而使用
make_shared
new + shared_ptr
make_shared
尽管
make_shared
std::shared_ptr<Foo> ptr(new Foo, [](Foo* p){ /* custom cleanup */ });std::make_shared
new
如果类的构造函数不是公开的,
make_shared
weak_ptr
make_shared
weak_ptr
weak_ptr
这是因为控制块和对象共用一块内存。而
new + shared_ptr
weak_ptr
所以,如果你预期对象很快析构但
weak_ptr
make_shared
| 场景 | 推荐方式 |
|---|---|
| 普通对象创建,无特殊需求 | ✅ 优先使用 @@######@@ |
| 需要自定义删除器 | ❌ 必须用 @@######@@ + @@######@@ |
| 构造函数非 public | ❌ 通常不能用 @@######@@ |
| 对象生命周期短但 @@######@@ 长期存在 | ⚠️ 谨慎使用 @@######@@,考虑内存延迟释放问题 |
| 高性能关键路径 | ✅ 优先 @@######@@,减少分配和提升缓存效率 |
std::make_shared
new
shared_ptr
make_shared
weak_ptr
基本上就这些,不复杂但容易忽略细节。
make_shared
make_shared
make_shared
new + shared_ptr
new
std::make_shared
new
以上就是make_shared和new有什么区别 性能优势与内存分配分析的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号