智能指针简介
头文件&分类
智能指针都在memory中, 有auto_ptr, unique_ptr, shared_ptr, weak_ptr
智能指针发展史
C++98就有智能指针了(auto_ptr)
c++11前,智能指针主要靠boost(第三方库)
C++11引进了boost智能指针
raii是啥
是一种技术手段, 将管理一份资源的责任托管给了一个对象
模拟实现智能指针(auto_ptr)
就像把它变为局部变量,出作用域自动销毁
重载* -> 后可模拟普通指针行为
智能指针初始化
Auto_ptr缺点&改进措施
拷贝很头疼:多次析构同一空间会报错
解决方法:
unique_ptr防拷贝,防赋值
share_ptr引用计数, 最后才拷贝
各种智能指针比较
Auto_ptr
不建议用,因为有缺陷,标准委员会建议:什么情况下都不要使用auto_ptr
auto_ptr有拷贝,其实为管理权转移,原指针失效效,不可使用,很坑
所以建议unique_ptr,不提供拷贝构造
管理权转移实现:
unique_ptr
问题:不支持多引用
定制删除器管理数组(不必要,建议classname[]即可)
shared_ptr
支持classname[],支持定制删除器但传参方式不一样
问题:不可循环引用
循环引用
weak_str
weak_ptr的唯一作用就是解决shared_ptr中存在的循环引用问题
不能独立使用, 必须配合shared_ptr
不支持管理资源
不支持acii
Weak_str解决循环引用示例:
#include <iostream>
#include <memory>
class B; // 先声明 B,因为 A 需要持有 B 的 shared_ptr
class A {
public:
std::shared_ptr<B> b_ptr;
A() {
std::cout << "A constructor\n";
}
~A() {
std::cout << "A destructor\n";
}
};
class B {
public:
std::weak_ptr<A> a_weak_ptr;
B() {
std::cout << "B constructor\n";
}
~B() {
std::cout << "B destructor\n";
}
};
int main() {
std::shared_ptr<A> a_ptr = std::make_shared<A>();
std::shared_ptr<B> b_ptr = std::make_shared<B>();
// 设定双向引用
a_ptr->b_ptr = b_ptr;
b_ptr->a_weak_ptr = a_ptr;
// 此时 a_ptr 和 b_ptr 都还在作用域内
// 手动释放 a_ptr,观察 weak_ptr 的行为
a_ptr.reset();
// 此时 a_ptr 对象被释放,但 b_ptr 仍然持有 weak_ptr 指向 a_ptr
// 可以尝试访问 weak_ptr
if (auto a_shared_ptr = b_ptr->a_weak_ptr.lock()) {
std::cout << "Accessing A via weak_ptr inside B\n";
} else {
std::cout << "A has been destroyed\n";
}
// 在这里 b_ptr 被释放,B 对象也会被销毁
return 0;
}
Lock
将 weak_ptr 转换为 std::shared_ptr
作用:安全转换为 shared_ptr:lock() 尝试将持有的 weak_ptr 转换为 shared_ptr。如果 weak_ptr 对象所引用的 shared_ptr 对象仍然存在,则 lock() 返回一个指向这个对象的 shared_ptr。这样可以安全地访问对象的资源,而不用担心对象已经被销毁。
#include <iostream>
#include <memory>
int main() {
std::shared_ptr<int> shared = std::make_shared<int>(10);
std::weak_ptr<int> weak = shared;
// 使用 weak_ptr 的 lock() 方法转换为 shared_ptr
if (auto locked = weak.lock()) {
std::cout << "Value of shared_ptr: " << *locked << std::endl;
// 这里可以安全地使用 locked,因为对象仍然存在
} else {
std::cout << "shared_ptr is no longer available." << std::endl;
}
// 当 shared_ptr 被释放后
shared.reset();
// 再次尝试访问,此时 locked 变成空指针
if (auto locked = weak.lock()) {
std::cout << "Value of shared_ptr: " << *locked << std::endl;
} else {
std::cout << "shared_ptr is no longer available." << std::endl;
}
return 0;
}