C++智能指针通过RAII机制自动管理内存,避免泄漏和悬空指针。std::unique_ptr独占所有权,高效安全;std::shared_ptr共享所有权,用引用计数管理生命周期;std::weak_ptr打破循环引用,实现非拥有式观察,三者结合STL容器可简化资源管理。

C++的智能指针,在我看来,是现代C++编程中处理内存管理的一剂良药,它极大地简化了资源管理,尤其是在与STL容器结合使用时,能有效避免内存泄漏和悬空指针等常见问题。它本质上就是一种RAII(Resource Acquisition Is Initialization)的实践,把资源的生命周期与对象的生命周期绑定起来,当对象超出作用域时,资源也自动释放。这比手动管理内存省心太多了,也更安全。
在C++中,要妥善管理内存,特别是配合STL容器使用时,智能指针是不可或缺的工具。核心方案是根据所有权模型选择合适的智能指针类型:
std::unique_ptr
std::shared_ptr
std::weak_ptr
std::vector<std::unique_ptr<MyObject>>
std::unique_ptr
std::unique_ptr
unique_ptr
它特别适合用在以下场景:
立即学习“C++免费学习笔记(深入)”;
举个例子,如果你有一个
std::vector
vector
std::vector<std::unique_ptr<MyClass>>
vector
unique_ptr
MyClass
vector
delete
#include <iostream>
#include <memory> // For std::unique_ptr
#include <vector>
class MyResource {
public:
MyResource(int id) : id_(id) {
std::cout << "MyResource " << id_ << " constructed." << std::endl;
}
~MyResource() {
std::cout << "MyResource " << id_ << " destructed." << std::endl;
}
void doSomething() {
std::cout << "MyResource " << id_ << " doing something." << std::endl;
}
private:
int id_;
};
// 示例:unique_ptr 作为函数返回值,转移所有权
std::unique_ptr<MyResource> createResource(int id) {
return std::make_unique<MyResource>(id);
}
int main() {
// 独占所有权示例
std::unique_ptr<MyResource> res1 = std::make_unique<MyResource>(1);
res1->doSomething();
// 所有权转移
std::unique_ptr<MyResource> res2 = std::move(res1); // res1 变为空
if (res1) {
std::cout << "res1 still holds resource." << std::endl;
} else {
std::cout << "res1 no longer holds resource." << std::endl;
}
res2->doSomething();
// unique_ptr 和 STL 容器
std::vector<std::unique_ptr<MyResource>> resources;
resources.push_back(std::make_unique<MyResource>(3));
resources.push_back(createResource(4)); // 函数返回 unique_ptr
for (const auto& r_ptr : resources) {
r_ptr->doSomething();
}
// main 函数结束时,res2 和 resources 中的 MyResource 对象都会被自动销毁
std::cout << "End of main function." << std::endl;
return 0;
}std::shared_ptr
当多个对象需要共享同一个资源的生命周期时,
std::shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
它适用于:
比如,你有一个缓存系统,多个客户端可能会访问同一个数据对象。每个客户端都持有一个
shared_ptr
#include <iostream>
#include <memory> // For std::shared_ptr
#include <vector>
class SharedResource {
public:
SharedResource(int id) : id_(id) {
std::cout << "SharedResource " << id_ << " constructed." << std::endl;
}
~SharedResource() {
std::cout << "SharedResource " << id_ << " destructed." << std::endl;
}
void use() {
std::cout << "SharedResource " << id_ << " is being used. Current ref count: "
<< shared_from_this().use_count() << std::endl;
}
private:
int id_;
};
int main() {
std::shared_ptr<SharedResource> s_res1 = std::make_shared<SharedResource>(100);
std::cout << "s_res1 ref count: " << s_res1.use_count() << std::endl;
std::shared_ptr<SharedResource> s_res2 = s_res1; // 拷贝,引用计数增加
std::cout << "s_res1 ref count: " << s_res1.use_count() << std::endl;
std::cout << "s_res2 ref count: " << s_res2.use_count() << std::endl;
{
std::shared_ptr<SharedResource> s_res3 = s_res1; // 再次拷贝
std::cout << "s_res1 ref count: " << s_res1.use_count() << std::endl;
s_res3->use();
} // s_res3 离开作用域,引用计数减少
std::cout << "s_res1 ref count after s_res3 out of scope: " << s_res1.use_count() << std::endl;
// shared_ptr 和 STL 容器
std::vector<std::shared_ptr<SharedResource>> shared_resources_vec;
shared_resources_vec.push_back(s_res1); // s_res1 再次被拷贝
shared_resources_vec.push_back(std::make_shared<SharedResource>(200));
std::cout << "s_res1 ref count after vector push_back: " << s_res1.use_count() << std::endl;
// main 函数结束时,所有 SharedResource 对象都会在引用计数归零时被销毁
std::cout << "End of main function." << std::endl;
return 0;
}std::weak_ptr
std::weak_ptr
std::shared_ptr
shared_ptr
shared_ptr
当两个或多个对象通过
shared_ptr
weak_ptr
shared_ptr
weak_ptr
weak_ptr
要访问
weak_ptr
lock()
std::shared_ptr
lock()
shared_ptr
shared_ptr
使用场景:
shared_ptr
shared_ptr
weak_ptr
说实话,刚接触
weak_ptr
unique_ptr
shared_ptr
weak_ptr
#include <iostream>
#include <memory> // For std::shared_ptr, std::weak_ptr
class B; // 前向声明
class A {
public:
std::shared_ptr<B> b_ptr;
A() { std::cout << "A constructed." << std::endl; }
~A() { std::cout << "A destructed." << std::endl; }
void link(std::shared_ptr<B> b) {
b_ptr = b;
}
};
class B {
public:
std::weak_ptr<A> a_ptr; // 使用 weak_ptr 打破循环
B() { std::cout << "B constructed." << std::endl; }
~B() { std::cout << "B destructed." << std::endl; }
void link(std::shared_ptr<A> a) {
a_ptr = a;
}
void accessA() {
if (auto sp = a_ptr.lock()) { // 尝试获取 shared_ptr
std::cout << "B can access A." << std::endl;
} else {
std::cout << "A no longer exists." << std::endl;
}
}
};
int main() {
std::cout << "--- 循环引用问题(使用 weak_ptr 解决) ---" << std::endl;
{
std::shared_ptr<A> my_a = std::make_shared<A>();
std::shared_ptr<B> my_b = std::make_shared<B>();
// 相互引用
my_a->link(my_b);
my_b->link(my_a);
std::cout << "my_a ref count: " << my_a.use_count() << std::endl; // 应该是 1 (my_a自己)
std::cout << "my_b ref count: " << my_b.use_count() << std::endl; // 应该是 2 (my_b自己 + my_a->b_ptr)
my_b->accessA(); // 此时 A 仍然存在
} // my_a 和 my_b 离开作用域
std::cout << "--- 离开作用域后,对象是否被销毁? ---" << std::endl;
// 由于 B 中使用了 weak_ptr,A 的引用计数会归零,A 会被销毁。
// A 销毁后,其持有的 B 的 shared_ptr 也会失效,B 的引用计数归零,B 也会被销毁。
// 如果 B 中也用 shared_ptr,则 A 和 B 都不会被销毁。
// 再次尝试访问已销毁的 A
std::shared_ptr<A> expired_a;
std::shared_ptr<B> observer_b = std::make_shared<B>();
observer_b->link(expired_a); // link to a null shared_ptr
observer_b->accessA(); // 应该输出 "A no longer exists."
std::cout << "End of main function." << std::endl;
return 0;
}以上就是C++智能指针 STL内存管理方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号