c++++智能指针主要有unique_ptr、shared_ptr和weak_ptr三种类型,它们基于raii原则实现自动化内存管理,避免内存泄漏和悬空指针问题;unique_ptr提供独占所有权且高效,适用于单一所有者场景;shared_ptr通过引用计数实现共享所有权,适合多对象共用资源的情况;weak_ptr作为弱引用不增加引用计数,用于打破shared_ptr的循环引用并安全观察对象生命周期,三者结合使用可显著提升c++程序的内存安全与代码健壮性。

C++智能指针主要有三种类型:
unique_ptr
shared_ptr
weak_ptr
说实话,刚接触C++那会儿,手动管理内存真是个噩梦。
new
delete
delete
这三种智能指针各司其职,解决了不同场景下的内存所有权问题。
unique_ptr
shared_ptr
weak_ptr
shared_ptr
立即学习“C++免费学习笔记(深入)”;
unique_ptr
unique_ptr
unique_ptr
unique_ptr
它特别适合那些资源必须有且只有一个明确所有者的场景,比如文件句柄、网络连接、或者某个类的内部成员,这些资源一旦被创建,就应该由某个特定的实体负责其生命周期。当你需要将资源的所有权从一个地方转移到另一个地方时,
std::move
#include <iostream>
#include <memory>
#include <vector>
class MyResource {
public:
MyResource(int id) : id_(id) {
std::cout << "MyResource " << id_ << " created." << std::endl;
}
~MyResource() {
std::cout << "MyResource " << id_ << " destroyed." << std::endl;
}
void do_something() {
std::cout << "MyResource " << id_ << " doing something." << std::endl;
}
private:
int id_;
};
void process_resource(std::unique_ptr<MyResource> res) {
if (res) { // 检查是否为空
res->do_something();
}
// res 在这里超出作用域,MyResource 自动销毁
}
int main() {
// 创建一个 unique_ptr
std::unique_ptr<MyResource> ptr1 = std::make_unique<MyResource>(1);
ptr1->do_something();
// 尝试复制会编译错误:
// std::unique_ptr<MyResource> ptr2 = ptr1; // 编译错误
// 移动所有权
std::unique_ptr<MyResource> ptr2 = std::move(ptr1);
if (!ptr1) { // ptr1 现在是空的
std::cout << "ptr1 is now empty after move." << std::endl;
}
ptr2->do_something();
// 将所有权传递给函数
process_resource(std::move(ptr2));
if (!ptr2) {
std::cout << "ptr2 is now empty after passing to function." << std::endl;
}
// 在容器中使用 unique_ptr
std::vector<std::unique_ptr<MyResource>> resources;
resources.push_back(std::make_unique<MyResource>(3));
resources.push_back(std::make_unique<MyResource>(4));
// 当 resources 向量超出作用域时,其中的 MyResource 对象也会自动销毁
std::cout << "Main function ending." << std::endl;
return 0;
}使用
std::make_unique
unique_ptr
shared_ptr
有时候,一个资源可能需要被多个地方共同拥有,比如一个配置对象,或者一个大的数据结构,多个模块都需要访问它,并且当最后一个使用者不再需要它时,它才应该被销毁。这时,
shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
这种机制听起来很方便,确实也解决了许多复杂场景下的内存管理问题。比如在构建图结构、观察者模式或者缓存系统时,
shared_ptr
#include <iostream>
#include <memory>
#include <vector>
class SharedResource {
public:
SharedResource(int id) : id_(id) {
std::cout << "SharedResource " << id_ << " created." << std::endl;
}
~SharedResource() {
std::cout << "SharedResource " << id_ << " destroyed." << std::endl;
}
void use() {
std::cout << "SharedResource " << id_ << " is being used." << std::endl;
}
private:
int id_;
};
int main() {
std::shared_ptr<SharedResource> ptrA = std::make_shared<SharedResource>(100);
std::cout << "ptrA ref count: " << ptrA.use_count() << std::endl; // 1
std::shared_ptr<SharedResource> ptrB = ptrA; // 复制所有权
std::cout << "ptrA ref count: " << ptrA.use_count() << std::endl; // 2
std::cout << "ptrB ref count: " << ptrB.use_count() << std::endl; // 2
{
std::shared_ptr<SharedResource> ptrC = ptrA; // 再次复制
std::cout << "ptrA ref count: " << ptrA.use_count() << std::endl; // 3
ptrC->use();
} // ptrC 超出作用域,引用计数减1
std::cout << "ptrA ref count after C out of scope: " << ptrA.use_count() << std::endl; // 2
ptrB.reset(); // ptrB 放弃所有权,引用计数减1
std::cout << "ptrA ref count after B reset: " << ptrA.use_count() << std::endl; // 1
// 当 ptrA 超出作用域时,引用计数变为0,SharedResource 100 被销毁
std::cout << "Main function ending." << std::endl;
return 0;
}同样,
std::make_shared
shared_ptr
new
shared_ptr
shared_ptr
weak_ptr
weak_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
weak_ptr
shared_ptr
weak_ptr
weak_ptr
lock()
shared_ptr
lock()
shared_ptr
shared_ptr
这使得
weak_ptr
#include <iostream>
#include <memory>
class B; // 前向声明
class A {
public:
std::shared_ptr<B> b_ptr;
A() { std::cout << "A created." << std::endl; }
~A() { std::cout << "A destroyed." << std::endl; }
};
class B {
public:
std::weak_ptr<A> a_ptr; // 使用 weak_ptr 避免循环引用
B() { std::cout << "B created." << std::endl; }
~B() { std::cout << "B destroyed." << std::endl; }
void check_a() {
if (auto sharedA = a_ptr.lock()) { // 尝试获取 shared_ptr
std::cout << "B can still access A." << std::endl;
} else {
std::cout << "A has been destroyed." << std::endl;
}
}
};
int main() {
std::cout << "--- Demonstrating shared_ptr circular reference (conceptual) ---" << std::endl;
// 如果这里 A 和 B 都用 shared_ptr 互相引用,它们将永远不会被销毁
// std::shared_ptr<A> a = std::make_shared<A>();
// std::shared_ptr<B> b = std::make_shared<B>();
// a->b_ptr = b;
// b->a_ptr = a; // 引用计数永远不会归零
std::cout << "\n--- Demonstrating weak_ptr breaking circular reference ---" << std::endl;
std::shared_ptr<A> a_obj = std::make_shared<A>();
std::shared_ptr<B> b_obj = std::make_shared<B>();
a_obj->b_ptr = b_obj; // A 强引用 B
b_obj->a_ptr = a_obj; // B 弱引用 A
std::cout << "A ref count: " << a_obj.use_count() << std::endl; // 1 (只有 b_obj->a_ptr 不增加引用计数)
std::cout << "B ref count: " << b_obj.use_count() << std::endl; // 2 (a_obj->b_ptr 和 b_obj 自身)
b_obj->check_a(); // A 还在,可以访问
// 销毁 a_obj
a_obj.reset();
std::cout << "A ref count after reset: " << (a_obj ? a_obj.use_count() : 0) << std::endl; // 0
std::cout << "B ref count after A reset: " << b_obj.use_count() << std::endl; // 1 (只有 b_obj 自身)
b_obj->check_a(); // A 已经销毁,无法访问
std::cout << "Main function ending." << std::endl;
return 0;
}通过
weak_ptr
shared_ptr
总结一下,C++的智能指针家族为我们提供了强大的工具来管理动态内存。
unique_ptr
shared_ptr
weak_ptr
shared_ptr
以上就是C++智能指针有哪些类型 unique_ptr shared_ptr weak_ptr用法的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号