Qt和Standard C++智能指针比较

一、相关知识总结
C++的智能指针是通过模版类来实现的。其中,模版(template)让它可以匹配任一指针类型,(记住,它默认匹配指针类型);类,将指针模版进行封装,在析构函数中进行delete操作,由于类对象过期时(或遇到异常栈回滚时),会自动调用析构函数,故可以实现自动堆内存管理。参考《C++ Primer Plus》
Standard C++提供三种智能指针:auto_ptr、unique_ptr和shared_ptr。包含“#include"。
其中,auto_ptr已弃用,unique_ptr用于非复制内存管理(不允许复制),可匹配数组;shared_ptr采用引用计数(reference-count),可以管理多个指向同一堆内存的指针,允许复制。
注:智能指针模版类,仅用于管理堆内存,不可以用于非堆内存,静态内存区???

Qt提供了三种指针模版类:QPointer、QScopedPointer(类似于std::auto_ptr)和QSharedPointer(类似于std::shared_ptr)。参考《An Introducttion of Design Pattern in C++ with Qt》和Qt帮助文档。
其中,”The QPointer class is a template class that provides guarded pointers to QObject.“,它主要管理QObject对象及其子类对象。在Qt中,用处比较少,一般Qt中常采用指定父对象的方式来管理子对象。
Qt中另外两个指针模版类,可以管理任意堆内存。相对于std,它们提供了几个convenience functions。

二、测试示例
用QCreator新建一个默认的MainWindow工程,修改main()函数,如下
工程一,测试QPointer
#include "mainwindow.h"
#include 
#include 

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
//    MainWindow w;
//    w.show();
    {
        QPointer<MainWindow> pWindow(new MainWindow());
        pWindow->show();
    }

    return a.exec();
}

在构造函数和析构函数中添加了打印log,测试过程中,运行出内部花括符外,未调用析构函数,关闭窗口,亦未调用析构函数,测试失败。
工程二,测试QScopedPointer:
首先,将上述代码中的”QPointer“替换为”QScopedPointer“,直接测试,运行出内部花括符后,调用析构函数,测试成功。
然后,在测试用测试QScopedPointer管理数组,
 
     
QScopedPointer pArray(new int[5]);
for (int i = 0; i < 5; i++)
{
   *pArray++ = 2*i;
    //pArray[i] = 2*i;
}
编译报错,换成std::unique_ptr,也有相同的错误。分析:智能指针模版类,仅重载了解引用“*”和调用“->”两个运算符,没有重载“++”和“[]”运算符。
在standar c++中,推荐使用boost库中的scoped_arrayshared_array管理动态数组,参考:C++智能指针处理动态数组。当然,能够用容器,最好用容器。
在Qt中,亦提供相应的模版类:QScopedArrayPointer等。探索应用:
1,std::unique_ptr
先开辟堆空间,并赋给普通指针,再用智能指针管理堆空间
 
     


{
    int * pArray = new int[5];
    std::unique_ptr ptrArray(pArray);
    for (int i = 0; i < 5; i++)
    {
        pArray[i] =2 * i;
    }
    PrintFunc(pArray, 5);
}
// void PrintFunc(int * ptrInt, int nSize); 采用传址方式的C风格函数调用
上述代码已测试,可以自动回收堆内存。使用QScopedPointer替换std::unique_ptr,效果相同。



你可能感兴趣的:(Qt)