make_shared更优的核心原因在于其将对象与控制块合并为一次内存分配,从而提升性能与内存局部性。1. make_shared通过单次内存分配同时创建对象和控制块,减少系统调用开销并优化缓存利用率;2. 直接构造shared_ptr需两次独立分配,影响效率且降低内存局部性;3. 特定场景如需自定义删除器、接管原始指针或精细控制weak_ptr生命周期时,应使用直接构造方式。

简而言之,
make_shared
new
shared_ptr

当我们谈论
make_shared
shared_ptr
make_shared<T>(args...)
T
shared_ptr
而如果采用
shared_ptr<T>(new T(args...))
new T(args...)
T
shared_ptr

这种差异直接影响到性能和内存使用效率。我个人在项目实践中,几乎总是优先考虑
make_shared
make_shared
make_shared

首先是性能优势。进行一次内存分配操作通常比两次要快,这减少了系统调用的开销。尤其是在需要频繁创建大量
shared_ptr
其次是内存局部性。由于对象和其控制块被分配在同一块连续的内存区域,它们在内存中的位置是相邻的。这对于CPU缓存来说非常友好。当程序访问对象时,很有可能其控制块的数据也已经被加载到缓存中,反之亦然。这种良好的内存局部性可以有效减少缓存未命中的情况,从而提高程序的运行效率。在现代CPU架构下,缓存的效率对程序性能的影响是巨大的,甚至可能比原始的指令执行速度更重要。
举个例子,假设我们有一个简单的结构体:
struct MyData {
int value;
std::string name;
// ... 更多数据
};
// 使用 make_shared
auto data1 = std::make_shared<MyData>();
// 直接构造
auto data2 = std::shared_ptr<MyData>(new MyData());在
data1
MyData
shared_ptr
data2
new MyData()
shared_ptr
shared_ptr
尽管
make_shared
shared_ptr<T>(new T(...))
一个非常常见的例子是当你需要自定义删除器(custom deleter)时。
make_shared
shared_ptr
// 假设有一个C库函数,返回一个需要手动释放的指针
void* create_resource();
void destroy_resource(void*);
// 使用自定义删除器
std::shared_ptr<void> resource_ptr(create_resource(), [](void* p) {
std::cout << "Custom deleter called for resource." << std::endl;
destroy_resource(p);
});在这种情况下,
make_shared
另一个重要的场景是当你需要从已有的原始指针创建
shared_ptr
new
shared_ptr
delete
shared_ptr
// 假设some_c_api_func返回一个堆分配的指针 MyClass* raw_ptr = some_c_api_func(); // 将原始指针的所有权转移给shared_ptr std::shared_ptr<MyClass> managed_ptr(raw_ptr);
这里你不能用
make_shared
new MyClass()
raw_ptr
还有一种比较微妙但很重要的场景,与
weak_ptr
weak_ptr
weak_ptr
make_shared
shared_ptr
make_shared
weak_ptr
weak_ptr
shared_ptr<T>(new T())
shared_ptr
weak_ptr
new
深入到内存分配层面,
shared_ptr
使用
make_shared<T>()
T
shared_ptr
// 概念上,make_shared的内存布局可能是这样的: // [ MyObject数据 ... | shared_ptr控制块数据 (强/弱引用计数等) ... ] // ^----------------- 单次内存分配 ----------------------------------^
而当你通过
shared_ptr<T>(new T())
new T()
T
shared_ptr
// 概念上,直接构造的内存布局可能是这样的: // [ MyObject数据 ... ] <-- 第一次内存分配 (by new T()) // // [ shared_ptr控制块数据 (强/弱引用计数等) ... ] <-- 第二次内存分配 (by shared_ptr ctor)
这种分离的内存布局,就是导致前述“弱引用延迟释放”问题的根源。如果对象内部有一个
weak_ptr
shared_ptr
weak_ptr
make_shared
weak_ptr
因此,在大多数情况下,
make_shared
weak_ptr
shared_ptr
以上就是make_shared和直接构造shared_ptr有什么区别 性能与内存分配对比的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号