std::make_shared
和直接使用 std::shared_ptr
初始化是 C++ 中创建共享智能指针的两种不同方式。它们之间的主要区别在于内存分配、效率、异常安全性和使用上的便利性。
-
内存分配:
std::shared_ptr
直接初始化时,可能会涉及两次内存分配:一次用于分配被管理的对象,一次用于分配引用计数块(控制块)。std::make_shared
则将被管理的对象和引用计数块(控制块)一起分配在同一块内存上,这样可以减少内存分配的次数,提高内存使用效率。
-
效率:
std::make_shared
通常更高效,因为它减少了内存分配的次数,并且由于内存是连续分配的,可能会更好地利用缓存。
-
异常安全性:
- 当使用
std::shared_ptr
直接初始化时,如果对象的构造函数抛出异常,已经分配的控制块不会被正确释放,可能会导致内存泄漏。 std::make_shared
保证了即使构造函数抛出异常,内存也会被正确释放,因为它将对象和控制块的分配和构造合并为一个原子操作。
- 当使用
-
使用上的便利性:
std::make_shared
可以方便地传递参数给被管理对象的构造函数,特别是当对象构造函数有多个参数时。std::shared_ptr
直接初始化时,如果需要传递参数给对象的构造函数,可能需要额外的包装代码。
-
语法简洁性:
std::make_shared
通常提供更简洁的语法,特别是当需要创建一个共享指针并立即初始化它时。
下面是一个使用 std::make_shared
和直接初始化 std::shared_ptr
的例子:
使用 std::make_shared
:
auto ptr = std::make_shared<MyClass>(arg1, arg2, arg3);
直接初始化 std::shared_ptr
:
std::shared_ptr<MyClass> ptr(new MyClass(arg1, arg2, arg3));
在实际使用中,推荐使用 std::make_shared
,因为它更高效、更安全,并且在语法上更简洁。然而,有时候你可能需要使用 std::shared_ptr
的直接初始化,比如当你需要在创建智能指针时立即获取原始指针或者需要与旧代码兼容时。