Qt:智能指针QScopedPointer 的使用(以及如何写一个QScopedPointer )
前言
本文讲述QScopedPointer
的使用,以及自己如何写一个QScopedPointer
.
正文
QScopedPointer
的常用方法
以下是 QScopedPointer
的一些常用方法及其详细说明:
-
构造函数:
QScopedPointer<T> ptr(new T);
- 用于创建一个
QScopedPointer
,并管理一个新分配的对象。
-
reset()
:void reset(T *ptr = nullptr);
- 释放当前管理的对象并重新指向新的对象。如果传入
nullptr
,则仅释放当前管理的对象。
-
operator->()
:T *operator->() const;
- 用于访问指针指向的对象的成员函数或变量。
-
operator*()
:T &operator*() const;
- 用于访问指针指向的对象。
-
T *data()
:- 返回指针指向的对象的裸指针。
-
T *get() const noexcept
- 功能:与
data()
功能相同,也返回当前QScopedPointer
管理的对象的裸指针。 noexcept
:表示该函数不会抛出异常。- 用法:通常与
data()
等效,可以使用get()
方法来访问裸指针。
- 功能:与
-
bool isNull() const noexcept
- 功能:检查
QScopedPointer
是否为空(即它是否指向一个有效的对象)。 noexcept
:表示该函数不会抛出异常。- 用法:用于检查智能指针是否为空,常用于条件判断。
- 功能:检查
-
T *take() noexcept
- 功能:释放
QScopedPointer
管理的对象并返回裸指针,智能指针不再管理该对象。 noexcept
:表示该函数不会抛出异常。- 用法:当你需要将对象的所有权转移到外部使用时,可以使用
take()
方法。调用take()
后,智能指针不再管理该对象,因此外部代码需要负责删除它。
- 功能:释放
-
void swap(QScopedPointer<T, Cleanup> &other) noexcept
- 功能:交换当前
QScopedPointer
和另一个QScopedPointer
的管理对象。 noexcept
:表示该函数不会抛出异常。- 用法:用于交换两个
QScopedPointer
的对象,常用于实现自定义类型的swap
操作或在算法中交换两个智能指针。
- 功能:交换当前
使用示例
// TestSmartPointer.h
#ifndef TESTSMARTPOINTER_H
#define TESTSMARTPOINTER_H
#include <QObject>
#include <QScopedPointer>
#include <QSharedPointer>
class TestSmartPointer:public QObject
{
Q_OBJECT
public:
TestSmartPointer();
~TestSmartPointer();
void doSomething();
};
#endif // TESTSMARTPOINTER_H
// TestSmartPointer.cpp
#include "testsmartpointer.h"
#include <QDebug>
TestSmartPointer::TestSmartPointer()
{
qDebug()<<"对象创建";
}
TestSmartPointer::~TestSmartPointer()
{
qDebug()<<"对象销毁";
}
void TestSmartPointer::doSomething()
{
qDebug()<<"其它处理逻辑";
}
// main.cpp
#include <QCoreApplication>
#include "testsmartpointer.h"
#include "QDebug"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QScopedPointer<TestSmartPointer> smartPointer(new TestSmartPointer());
smartPointer->doSomething();
TestSmartPointer* tPointer = smartPointer.data();
tPointer->doSomething();
// 仅仅释放当前对象
smartPointer.reset(nullptr);
if (smartPointer.isNull()) {
qDebug()<<"smartPointer is null";
} else {
qDebug()<<"smartPointer is not null";
}
QScopedPointer<TestSmartPointer> smartPointer2(new TestSmartPointer());
if (smartPointer2.isNull()) {
qDebug()<<"smartPointer2 is null";
} else {
qDebug()<<"smartPointer2 is not null";
}
// 智能指针不再管理该对象,需要自己管理
TestSmartPointer* tPointer2 = smartPointer2.take();
tPointer2->doSomething();
delete tPointer2;
return a.exec();
}
运行结果
实现类似 QScopedPointer
的智能指针
template <typename T>
class ScopedPointerSelf
{
public:
// 构造函数
explicit ScopedPointerSelf(T *ptr = nullptr) : m_ptr(ptr) {}
// 析构函数
~ScopedPointerSelf() {
delete m_ptr;
}
// 禁止复制
ScopedPointerSelf(const ScopedPointerSelf&) = delete;
ScopedPointerSelf& operator=(const ScopedPointerSelf&) = delete;
// 允许移动
ScopedPointerSelf(ScopedPointerSelf&& other) noexcept : m_ptr(other.m_ptr) {
other.m_ptr = nullptr;
}
ScopedPointerSelf& operator=(ScopedPointerSelf&& other) noexcept {
if (this != &other) {
delete m_ptr;
m_ptr = other.m_ptr;
other.m_ptr = nullptr;
}
return *this;
}
// 访问对象的方法
T* operator->() const {
return m_ptr;
}
// 解引用
T& operator*() const {
return *m_ptr;
}
bool operator!() const {
return !m_ptr;
}
bool isNull() const {
return !m_ptr;
}
// 重置指针
void reset(T *ptr = nullptr) {
delete m_ptr;
m_ptr = ptr;
}
// 释放指针
T* take() {
T *temp = m_ptr;
m_ptr = nullptr;
return temp;
}
// 获取裸指针
T* get() const {
return m_ptr;
}
private:
T *m_ptr;
};
解释
这里只是实现了一个简单的智能指针的功能,肯定和源码中的没法比,不过该有的功能也都有。
- 构造函数和析构函数:构造函数初始化指针,析构函数自动删除管理的对象。
- 禁用复制:禁用复制构造函数和赋值操作符,以防止不必要的对象复制。
- 移动构造函数和移动赋值操作符:允许移动构造和移动赋值,以便在移动时转移资源所有权。
- 重置和释放:提供
reset()
和take()
方法来管理指针的生命周期和获取裸指针。
使用
// 将我上述的内容放到testSmartPointer.h中,然后在main.cpp中
// 简单更改一下就能用了
#include <QCoreApplication>
#include "testsmartpointer.h"
#include "QDebug"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
ScopedPointerSelf<TestSmartPointer> smartPointer(new TestSmartPointer());
smartPointer->doSomething();
TestSmartPointer* tPointer = smartPointer.get();
tPointer->doSomething();
// 仅仅释放当前对象
smartPointer.reset(nullptr);
if (smartPointer.isNull()) {
qDebug()<<"smartPointer is null";
} else {
qDebug()<<"smartPointer is not null";
}
ScopedPointerSelf<TestSmartPointer> smartPointer2(new TestSmartPointer());
if (smartPointer2.isNull()) {
qDebug()<<"smartPointer2 is null";
} else {
qDebug()<<"smartPointer2 is not null";
}
// 智能指针不再管理该对象,需要自己管理
TestSmartPointer* tPointer2 = smartPointer2.take();
tPointer2->doSomething();
delete tPointer2;
return a.exec();
}
运行结果
小结
请指教