std::shared_ptr通过引用计数实现共享所有权,自动管理对象生命周期,避免内存泄漏和悬空指针;使用std::make_shared可提升性能与异常安全;需警惕循环引用,可用std::weak_ptr打破;其引用计数线程安全,但被管理对象的并发访问仍需额外同步机制。

C++的
std::shared_ptr
shared_ptr
std::shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
reset()
shared_ptr
shared_ptr
shared_ptr
这种机制的强大之处在于,它将资源的生命周期管理从程序员手中解放出来,自动化地处理了许多原本容易出错的场景。比如,你可以在不同的数据结构中存储指向同一个对象的
shared_ptr
delete
shared_ptr
创建
shared_ptr
std::make_shared
立即学习“C++免费学习笔记(深入)”;
#include <iostream>
#include <memory>
#include <string>
class MyResource {
public:
std::string name;
MyResource(const std::string& n) : name(n) {
std::cout << "MyResource " << name << " created." << std::endl;
}
~MyResource() {
std::cout << "MyResource " << name << " destroyed." << std::endl;
}
};
void processResource(std::shared_ptr<MyResource> res) {
std::cout << "Processing: " << res->name << ", current count: " << res.use_count() << std::endl;
} // res goes out of scope, ref count might decrease
int main() {
// 推荐使用 std::make_shared
std::shared_ptr<MyResource> res1 = std::make_shared<MyResource>("Data A");
std::cout << "Initial count for Data A: " << res1.use_count() << std::endl;
{
std::shared_ptr<MyResource> res2 = res1; // 拷贝,引用计数增加
std::cout << "Count after copy: " << res1.use_count() << std::endl;
processResource(res2); // 传递拷贝,函数内部又增加一次,然后减少
std::cout << "Count after function call: " << res1.use_count() << std::endl;
} // res2 goes out of scope, ref count decreases
std::cout << "Count before main scope ends: " << res1.use_count() << std::endl;
// main 结束时,res1 销毁,引用计数归零,MyResource "Data A" 被销毁
return 0;
}这段代码清晰地展示了
shared_ptr
MyResource
std::shared_ptr
没错,
shared_ptr
shared_ptr
shared_ptr
A -> shared_ptr<B>
B -> shared_ptr<A>
在这种情况下,当A和B的外部所有
shared_ptr
解决这个问题的关键在于引入
std::weak_ptr
weak_ptr
shared_ptr
shared_ptr
weak_ptr
要访问
weak_ptr
shared_ptr
weak_ptr::lock()
lock()
shared_ptr
lock()
shared_ptr
#include <iostream>
#include <memory>
#include <string>
class B; // 前向声明
class A {
public:
std::shared_ptr<B> b_ptr;
std::string name;
A(const std::string& n) : name(n) { std::cout << "A " << name << " created." << std::endl; }
~A() { std::cout << "A " << name << " destroyed." << std::endl; }
};
class B {
public:
std::weak_ptr<A> a_ptr; // 使用 weak_ptr 解决循环引用
std::string name;
B(const std::string& n) : name(n) { std::cout << "B " << name << " created." << std::endl; }
~B() { std::cout << "B " << name << " destroyed." << std::endl; }
void print_a_name() {
if (auto sharedA = a_ptr.lock()) { // 尝试获取 shared_ptr
std::cout << "B " << name << " accesses A: " << sharedA->name << std::endl;
} else {
std::cout << "A is no longer available for B " << name << std::endl;
}
}
};
int main() {
std::shared_ptr<A> myA = std::make_shared<A>("Instance A");
std::shared_ptr<B> myB = std::make_shared<B>("Instance B");
// 建立连接
myA->b_ptr = myB;
myB->a_ptr = myA; // 这里是 weak_ptr,不会增加 A 的引用计数
std::cout << "A's ref count: " << myA.use_count() << std::endl; // 应该是 1 (myA)
std::cout << "B's ref count: " << myB.use_count() << std::endl; // 应该是 1 (myB)
myB->print_a_name(); // B 可以安全地访问 A
// 当 myA 和 myB 超出作用域时,它们会被正确销毁
// A 的引用计数降为 0,A 销毁。
// B 的引用计数降为 0,B 销毁。
return 0;
}通过将其中一方的
shared_ptr
weak_ptr
std::make_shared
new
在C++中创建
shared_ptr
std::shared_ptr<T> p(new T(...));
std::shared_ptr<T> p = std::make_shared<T>(...);
从表面上看,它们都实现了同样的目的,但
std::make_shared
性能方面:
std::shared_ptr
weak_ptr
new T()
shared_ptr
T
shared_ptr
std::make_shared
T
shared_ptr
异常安全性方面: 考虑一个表达式,比如
func(std::shared_ptr<A>(new A()), std::shared_ptr<B>(new B()));
new A()
new B()
std::shared_ptr<A>(ptr_A)
std::shared_ptr<B>(ptr_B)
如果
new A()
new B()
ptr_A
std::shared_ptr<A>
A
shared_ptr
而使用
std::make_shared
func(std::make_shared<A>(), std::make_shared<B>());
std::make_shared<A>()
std::make_shared<B>()
std::make_shared<A>()
shared_ptr
A
make_shared
因此,除非你需要自定义删除器,或者需要从一个已经存在的裸指针来创建
shared_ptr
std::make_shared
std::shared_ptr
std::shared_ptr
shared_ptr
shared_ptr
shared_ptr
std::shared_ptr
shared_ptr
std::shared_ptr<MyResource> global_res = std::make_shared<MyResource>("Shared Data");
void thread_func() {
std::shared_ptr<MyResource> local_res = global_res; // 引用计数安全地增加
// ... 使用 local_res ...
} // local_res 销毁,引用计数安全地减少在这种情况下,
global_res
被管理对象的线程安全:
然而,std::shared_ptr
shared_ptr
std::mutex
shared_ptr
举个例子:
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
#include <vector>
class Counter {
public:
int value = 0;
std::mutex mtx; // 用于保护 value
void increment() {
std::lock_guard<std::mutex> lock(mtx);
value++;
}
};
std::shared_ptr<Counter> shared_counter = std::make_shared<Counter>();
void worker_thread() {
for (int i = 0; i < 1000; ++i) {
shared_counter->increment(); // 访问被 shared_ptr 管理的对象
}
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i) {
threads.emplace_back(worker_thread);
}
for (auto& t : threads) {
t.join();
}
std::cout << "Final counter value: " << shared_counter->value << std::endl;
return 0;
}在这个例子中,
shared_ptr
Counter
Counter
value
std::mutex
mtx
value
shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
std::atomic_load
std::atomic_store
shared_ptr
shared_ptr
总结来说,
shared_ptr
shared_ptr
shared_ptr
以上就是C++shared_ptr共享资源管理方法解析的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号