为什么需要智能指针?
在C++开发中,手动管理内存容易导致内存泄漏和悬空指针问题。Qt提供的QSharedPointer
通过自动内存管理,帮助我们更安全地操作堆对象。
QSharedPointer简介
- 共享所有权智能指针
- 采用引用计数机制
- 当最后一个指针离开作用域时,自动释放内存
- 支持自定义删除器(默认使用delete)
基础操作示例
1. 创建智能指针
// 创建空指针
QSharedPointer<int> ptr1;
// 动态分配内存
QSharedPointer<QString> ptr2(new QString("Hello"));
// 推荐使用工厂方法
auto ptr3 = QSharedPointer<QFile>::create("test.txt");
2. 共享所有权
QSharedPointer<Student> stuPtr(new Student("Alice"));
// 拷贝构造
QSharedPointer<Student> ptrCopy(stuPtr);
// 赋值操作
QSharedPointer<Student> ptrAssign;
ptrAssign = stuPtr;
// 此时引用计数为3
3. 重置指针
QSharedPointer<QObject> objPtr;
// 重置为新对象
objPtr.reset(new QObject());
// 重置为空指针
objPtr.reset();
4. 访问数据
QSharedPointer<QString> ptr2(new QString("Alice"));
if (!ptr2.isNull())
{
qDebug() << *ptr2; // 解引用操作
qDebug() << ptr2->toUpper(); // 箭头操作符
}
// 获取原始指针(慎用!)
QString* rawPtr = ptr2.data();
5. 判空操作
QSharedPointer<QString> ptr1(new QString("Alice"));
QSharedPointer<QString> ptr3(new QString("Alice"));
// 方式一
if (ptr1.isNull())
{
qDebug() << "Pointer is empty";
}
// 方式二(重载bool运算符)
if (!ptr3)
{
qDebug() << "Pointer is empty";
}
重要注意事项
-
避免循环引用
当两个QSharedPointer相互引用时会导致内存泄漏,此时应使用QWeakPointer
-
不要混合使用裸指针
QString* raw = new QString(); QSharedPointer<QString> p1(raw); // QSharedPointer<QString> p2(raw); // 错误!会导致重复删除
-
线程安全性
QSharedPointer的引用计数操作是原子性的,但指向的内容需要自行保证线程安全 -
自定义删除器
QSharedPointer<FILE> filePtr( fopen("data.bin", "rb"), [](FILE* f) { if(f) fclose(f); } );
什么时候使用?
✅ 需要共享所有权的场景
✅ 对象生命周期难以预测的情况
✅ 需要异常安全的代码
总结
QSharedPointer通过自动化内存管理,可以帮助开发者:
- 减少内存泄漏风险
- 简化资源管理代码
- 提高代码异常安全性
建议在Qt项目中优先使用智能指针替代裸指针!