shared_ptr缺陷以及为什么用make_shared
时间: 2023-08-23 17:11:49 浏览: 76
shared_ptr的一个主要缺陷是引发循环引用的问题。当两个或多个对象相互持有shared_ptr指针时,它们之间可能形成一个循环引用。这意味着即使没有其他对象引用它们,这些对象也无法被正确地销毁,因为它们的引用计数永远不会降为零。
另一个缺陷是每个shared_ptr对象都需要维护一个引用计数器,这会增加内存消耗和性能开销。当创建或销毁shared_ptr时,还需要进行原子操作以确保引用计数的正确性,这在多线程环境下可能会导致性能下降。
为了解决这些问题,C++11引入了make_shared函数。make_shared是一个模板函数,用于直接创建shared_ptr对象并初始化它所指向的对象。它可以避免循环引用问题,因为它在内部创建了一个单独的控制块来存储引用计数和其他元数据。这样,即使对象之间存在循环引用,它们也可以正确地被销毁,因为它们的引用计数可以降为零。
此外,使用make_shared可以减少内存消耗和提高性能。因为make_shared在同一块内存中同时存储对象和控制块,这样可以减少内存分配的开销,并且在引用计数方面也可以提供更好的性能。
总而言之,使用make_shared可以避免shared_ptr的循环引用问题,并提供更好的性能和内存效率。因此,在大多数情况下,推荐使用make_shared来创建shared_ptr对象。
相关问题
shared_ptr类型转shared_ptr*
要将 `shared_ptr` 转换为 `shared_ptr*`,你可以使用 `&` 运算符来获取 `shared_ptr` 对象的地址,然后将其转换为 `shared_ptr*` 类型的指针。以下是一个示例:
```cpp
#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> ptr = std::make_shared<int>(42);
std::shared_ptr<int>* ptrPtr = &ptr;
std::cout << "Address of shared_ptr: " << ptrPtr << std::endl;
return 0;
}
```
在上述示例中,`ptrPtr` 是一个指向 `shared_ptr<int>` 的指针,它指向 `ptr` 的地址。请注意,这里的 `ptrPtr` 是一个指向 `shared_ptr<int>` 的指针,而不是一个指向裸指针的指针。
记住,通过将 `shared_ptr` 转换为裸指针类型可能会失去智能指针的优势,因为裸指针不会自动管理内存。只有在特定情况下,比如与某些 C 接口函数交互时,才需要将 `shared_ptr` 转换为裸指针。在大多数情况下,应尽量使用智能指针的功能来管理内存。
shared_ptr和make_shared区别
shared_ptr和make_shared是C++中用于管理动态分配对象的智能指针。
1. shared_ptr:
- shared_ptr是一个类模板,用于管理动态分配对象的引用计数。
- shared_ptr可以指向任意动态分配的对象,并且可以共享所有权。
- 通过复制shared_ptr,引用计数会增加,当引用计数为0时,会自动释放关联的对象。
- shared_ptr需要额外的内存来存储引用计数,可能会导致一定的空间开销。
2. make_shared:
- make_shared是一个函数模板,用于直接创建并初始化shared_ptr。
- make_shared可以通过传递参数来创建对象,并将返回的shared_ptr指向该对象。
- make_shared在内存中一次性分配了用于存储对象和引用计数的内存块,可以减少空间开销。
- make_shared可以避免了显式使用new操作符来分配内存。
区别:
- 内存分配方式:shared_ptr使用单独的内存块存储引用计数,而make_shared在同一内存块中同时存储对象和引用计数。
- 性能和空间开销:make_shared通常比shared_ptr更高效,因为它只需要一次内存分配,并且可以减少空间开销。
- 使用场景:一般情况下,推荐使用make_shared,除非有特殊需求,如自定义内存分配器或需要显式控制资源释放的情况下,才使用shared_ptr。