面试题答案
一键面试std::shared_ptr
引用计数机制实现:std::shared_ptr
内部包含两个指针,一个指向对象,另一个指向控制块(control block)。- 控制块是一个动态分配的内存块,其中包含引用计数(reference count),可能还包含其他信息,比如弱引用计数(用于
std::weak_ptr
)等。 - 当通过
std::make_shared
或者直接构造std::shared_ptr
来指向一个对象时,会分配控制块并初始化引用计数为1。
- 引用计数增加情况:
- 拷贝构造:当使用
std::shared_ptr
的拷贝构造函数创建一个新的std::shared_ptr
对象时,如std::shared_ptr<int> ptr1 = std::make_shared<int>(10); std::shared_ptr<int> ptr2(ptr1);
,此时新对象ptr2
和原对象ptr1
指向同一个控制块,控制块中的引用计数加1。 - 赋值操作:当使用
std::shared_ptr
的赋值运算符时,如std::shared_ptr<int> ptr1 = std::make_shared<int>(10); std::shared_ptr<int> ptr2; ptr2 = ptr1;
,ptr2
原来指向的对象(如果有)的引用计数减1,ptr1
指向对象的引用计数加1。
- 拷贝构造:当使用
- 引用计数减少情况:
std::shared_ptr
对象析构:当std::shared_ptr
对象超出作用域或者被显式释放时,其析构函数会被调用。在析构函数中,控制块中的引用计数减1。如果引用计数减为0,意味着没有其他std::shared_ptr
对象指向该对象,那么会释放指向的对象以及控制块的内存。例如:
{ std::shared_ptr<int> ptr = std::make_shared<int>(10); } // 这里ptr超出作用域,引用计数减1变为0,对象和控制块内存被释放
- 重置(
reset
)操作:调用std::shared_ptr
的reset
成员函数时,如std::shared_ptr<int> ptr = std::make_shared<int>(10); ptr.reset();
,原对象的引用计数减1。如果减为0,同样会释放对象和控制块内存。reset
也可以用来指向新的对象,如ptr.reset(new int(20));
,此时原对象引用计数减1,新对象引用计数设为1。