std::shared_ptr
是 C++ 标准库中的一种智能指针,用于管理动态分配的对象生命周期。它通过引用计数机制实现多个 std::shared_ptr
共享对象的所有权。理解 std::shared_ptr
的原理需要从它的内部实现、引用计数机制以及线程安全性入手。
std::shared_ptr
的原理
1. 引用计数机制
std::shared_ptr
的核心是引用计数机制。每个由 std::shared_ptr
管理的对象都会关联一个控制块(control block),控制块中存储以下信息:
- 强引用计数(use count):记录当前有多少个
std::shared_ptr
共享对象的所有权。 - 弱引用计数(weak count):记录当前有多少个
std::weak_ptr
正在观察对象。 - 指向对象的指针:指向实际管理的对象。
- 删除器(deleter):用于自定义对象的销毁方式(可选)。
当一个新的 std::shared_ptr
指向同一个对象时,强引用计数会增加;当一个 std::shared_ptr
被销毁或重置时,强引用计数会减少。当强引用计数归零时,对象会被销毁,但控制块不会立即释放,直到弱引用计数也归零。
2. 控制块的创建
控制块的创建方式有两种:
- 通过
std::make_shared
创建:std::make_shared
会一次性分配内存,既存储对象又存储控制块。- 这种方式更高效,因为减少了内存分配次数。
- 通过
std::shared_ptr
构造函数创建:- 如果直接使用
new
创建对象并传递给std::shared_ptr
,则会单独分配控制块。 - 这种方式会导致两次内存分配(对象和控制块)。
- 如果直接使用
3. 共享所有权
多个 std::shared_ptr
可以共享同一个对象的所有权。每个 std::shared_ptr
都指向相同的控制块,并通过控制块管理对象的生命周期。
std::shared_ptr
的线程安全性
1. 引用计数的线程安全性
std::shared_ptr
的引用计数操作是原子的,因此多个线程同时拷贝或销毁std::shared_ptr
是线程安全的。
2. 对象访问的线程安全性
std::shared_ptr
只保证引用计数的线程安全性,不保证对象本身的线程安全性。- 如果多个线程同时访问同一个对象,需要额外的同步机制(如互斥锁)来保证线程安全。
3. 控制块的线程安全性
- 控制块的操作(如引用计数的增减)是线程安全的,但控制块中的其他数据(如删除器)可能不是线程安全的。
4. 注意事项
- 如果多个线程同时修改同一个
std::shared_ptr
对象(例如赋值或重置),可能会导致竞争条件。此时需要使用原子操作或互斥锁来保护。
使用示例
#include <iostream>
#include <memory>
#include <thread>
class MyClass {
public:
MyClass() { std::cout << "MyClass constructed!" << std::endl; }
~MyClass() { std::cout << "MyClass destroyed!" << std::endl; }
void doSomething() { std::cout << "Doing something!" << std::endl; }
};
void thread_func(std::shared_ptr<MyClass> ptr) {
std::this_thread::sleep_for(std::chrono::seconds(1));
ptr->doSomething();
}
int main() {
std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();
std::thread t1(thread_func, ptr);
std::thread t2(thread_func, ptr);
t1.join();
t2.join();
return 0;
}
输出:
MyClass constructed!
Doing something!
Doing something!
MyClass destroyed!
总结
- 原理:
std::shared_ptr
通过引用计数机制管理对象的生命周期。- 控制块存储引用计数和对象指针,多个
std::shared_ptr
共享同一个控制块。
- 线程安全性:
- 引用计数操作是线程安全的。
- 对象访问和控制块的其他操作需要额外的同步机制来保证线程安全。
这个问题考察的是对 std::shared_ptr
的实现原理和线程安全性的理解,是 C++ 面试中的常见题目。
THE END
暂无评论内容