shared_ptr 是一个类的模板,它使用引用计数的方式来管理一个动态分配的内存资源。shared_ptr 需要一个动态分配的对象时,会在堆上分配一块内存来存储该对象,并维护一个引用计数。
shared_ptr允许多个shared_ptr指向同一个对象,通过引用计数来跟踪有多少个shared_ptr指向同一个对象。每次创建一个新的shared_ptr指向同一个对象时,引用计数增加1。当一个shared_ptr离开作用域或被重置时,引用计数减少1。当引用计数变为0时,shared_ptr会自动删除所指向的对象并释放内存。
本文出现的关于shared_ptr
的方法都包含在此头文件中
#include
最安全方法是调用make_shared
的标准库函数。同时引用计数从0到1。
// 指向一个值为默认值的int的shared_ptr:0
std::shared_ptr<int> p1 = make_shared<int>();
// 指向一个值为4的int的shared_ptr
std::shared_ptr<int> pt2 = make_shared<int>(4);
// 指向一个值为"555555"的string的shared_ptr
std::shared_ptr<std::string> p3= make_shared<string>(6, '5');
通常用定义一个auto
对象来保存make_shared
结果
// 指向一个值为默认值的int的shared_ptr:0
auto p4 = make_shared<int>();
通过拷贝和赋值也可以初始化。
auto p = make_shared<int>(4); // p指向的引用对象只有p一个引用者,此对象引用计数为1
auto q(p); // p和q指向的相同对象,此对象引用计数递增变为2
auto r = make_shared<int>(4); // r指向的引用对象只有r一个引用者,引用计数为1
auto r = q; // 给r赋值,令它指向另一个地址
// 递增q指向的对象的引用计数,此对象引用计数变为3
// 递减r原来指向的对象的引用计数,此引用计数变为0,自动释放
#include
#include // for std::shared_ptr and std::unique_ptr
class Person
{
public:
Person(std::string name, int age) :m_name(name), m_age(age)
{
std::cout << "Create Person" << " " << m_name.c_str() << " " << m_age << std::endl;
};
~Person()
{
std::cout << "Destroy Person" << " " << m_name.c_str() << " " << m_age << std::endl;
};
private:
std::string m_name;
int m_age;
};
int main()
{
// 离开作用域场合
{
// 创建shared_ptr
std::shared_ptr<Person> sharedPtr = std::make_shared<Person>("Tom", 10);
// 输出引用计数( 结果:1)
std::cout << "SharedPtr uses" << " " << sharedPtr.use_count() << std::endl;
{
// sharedPtr2和sharedPtr指向同一个对象,此对象的引用计数递增,变为2
std::shared_ptr<Person> sharedPtr2 = sharedPtr; // sharedPtr2不会调用构造函数,因为这个指针和sharedPtr指向的是同一个内存地址
// 输出引用计数( 结果:2)
std::cout << "SharedPtr uses" << " " << sharedPtr.use_count() << std::endl;
}
// 当sharedPtr2离开作用域时,其指向对象的引用计数递减,变为1(此时还有sharedPtr指向该对象)。
std::cout << "SharedPtr uses" << " " << sharedPtr.use_count() << std::endl;
}
// 当sharedPtr离开作用域时,引用计数递减变为0。然后析构函数自动被调用,析构函数会检查 shared_ptr 的引用计数,如果计数为 0,则调用 reset 函数来释放对象(不用显示调用),并将指针设为null。
std::cout << "Hello World!\n";
return 0;
}