0
点赞
收藏
分享

微信扫一扫

【QT小记】QT中智能指针的使用

小亦同学321 2022-04-17 阅读 63
自定义两个类
class OnePiece {
public:
    OnePiece() {
        qDebug() << QString("构造OP");
    }
    ~OnePiece() {
        qDebug() << QString("~析构OP");
    }
public:
    void print() {
        qDebug() << QString("OP在拉夫德鲁");
    }
};

class Nika : public QObject {
public:
    Nika() {
        qDebug() << "构造尼卡";
    }
    ~Nika() {
        qDebug() << "析构尼卡";
    }

public:
    void print() {
        qDebug() << "这个时代,路飞是尼卡";
    }
};

QSharedPointer && QWeakPointer

  • QSharedPointer
    • 共享指针
    • 强引用
    • 线程安全
    • 内部采用引用计数,引用计数的原子机制的
    • 引用计数为0时,释放对象,删除原生指针
  • QWeakPointer
    • 线程安全
    • 弱引用
    • 不增加引用计数
    • 不能调用原生指针对象方法(没有重载operator*和->)
    • 配合QSharedPointer使用,解除循环引用问题
    // QSharedPointer + QWeakPointer
    qDebug() << "QSharedPointer Example Start...";
    //case1 引用计数
    {
        QSharedPointer<OnePiece> op1 = QSharedPointer<OnePiece>(new OnePiece);  //引用计数为1
        QSharedPointer<OnePiece> op2(op1);  //引用计数为2
        QSharedPointer<OnePiece> op3 = op1;  //引用计数为3
        op3->print();

        // 弱引用
        QWeakPointer<OnePiece> op4 = op1;  //引用计数为3
        // 弱引用转为强引用
        QSharedPointer<OnePiece> op5 = op4.toStrongRef();  //引用计数为4
        QSharedPointer<OnePiece> op6 = op4.lock();  //引用计数为5
        op6->print();
    }

    //case2 取出原生指针(不建议取出原生指针操作)
    {
        QSharedPointer<OnePiece> op = QSharedPointer<OnePiece>(new OnePiece);  //引用计数为1
        OnePiece *op1 = op.data();
        op1->print();
        OnePiece *op2 = op.get();
        op2->print();
    }

    //case3 清除对象 解除对原生指针的引用,若为最后一个引用,则删除对象
    {
        QSharedPointer<OnePiece> op1 = QSharedPointer<OnePiece>(new OnePiece);  //引用计数为1
        QSharedPointer<OnePiece> op2(op1);  //引用计数为2
        op2.clear();  //引用计数为1
        if (op2.isNull()) {
            qDebug() << "op2 is null";
        }
    }

    qDebug() << "QSharedPointer Example End...";

QScopedPointer

  • 独享指针(没有拷贝构造和赋值构造接口)
  • 没有引用计数
  • 线程安全
 // QScopedPointer
    qDebug() << "QScopedPointer Example Start...";
    // case1 独享指针
    {
        QScopedPointer<OnePiece> op(new OnePiece);
        op->print();
    }
    // case2 使用例子
    {
        auto func1 = [](int i){
            OnePiece *op = new OnePiece;
            if (i < 5) {
                delete op;  //不方便管理,这个位置可能会忘记delete
                return;
            }

            op->print();
            delete op;
            return ;
        };

        auto func2 = [](int i){
            QScopedPointer<OnePiece> op(new OnePiece);
            if (i < 5) {
                return;
            }

            op->print();
            return;
        };
    }
    // case3 取出原生指针
    {
        QScopedPointer<OnePiece> op(new OnePiece);
        OnePiece *op1 = op.data();  //op扔持有对象
        OnePiece *op2 = op.get();   //op扔持有对象
        qDebug() << (op.isNull() ? "op is null" : "op is not null");

        OnePiece *op3 = op.take();  //op为null
        qDebug() << (op.isNull() ? "op is null" : "op is not null");


        // 错误例子
        auto fun = []()->OnePiece * {
                QScopedPointer<OnePiece> op1(new OnePiece);
                op1->print();
                return op1.data();
//                OnePiece op1;
//                op1.print();
//                return &op1;
        };
        OnePiece *op7 = fun();  //fun()中op1被析构,所以会delete原生指针,所以op7会成为悬挂指针
        op7->print();           //测试后正常输出,有点奇怪???
    }

    qDebug() << "QScopedPointer Example End...";

QPointer

  • 只能使用于继承自QObject的类
  • 如果多个QPointer同时指向同一个对象,其中一个被delete,其它的QPointer则会被置为nullptr,避免了成为野指针的情况
// QPointer
    qDebug() << "QPointer Example Start...";

    {
        QPointer<Nika> nika1(new Nika);
        QPointer<Nika> nika2 = nika1;
        if (!nika1.isNull()) {
            nika1->print();
        }
        nika1.clear();
        if (nika1.isNull()) {
            qDebug() << "nika1 is null";
        }

        if (!nika2.isNull()) {
            nika2->print();
        }

        QPointer<Nika> nika3 = nika2;
        delete nika2;  //nika2被delete后,nika3也会被置为nullptr
        if (nika3.isNull()) {
            qDebug() << "nika3 is null";
        }
    }

    qDebug() << "QPointer Example End...";

QScopedArrayPointer

  • 使用于数组对象
// QScopedArrayPointer
    qDebug() << "QScopedArrayPointer Example Start...";

    {
        QScopedArrayPointer<OnePiece> ops(new OnePiece[3]);
        ops[0].print();
        //OnePiece op = ops[1];
        //op.print();
    }

    qDebug() << "QScopedArrayPointer Example End...";

QSharedDataPointer

  • 方便实现隐式共享类
  • 待补充

QExplicitlySharedDataPointer

  • 方便实现显示共享类
  • 待补充

Sevenlin++

目前在平时编码过程中基本不使用智能指针,还是在使用原生指针,这一点需要改进。有这么好的方式来管理指针,不用白不用,也可以避免指针管理不当造成的内存泄露。

举报

相关推荐

0 条评论