-
Qt的智能指针有几类,这里说的是QSharedPointer,即使用引用计数的智能指针。
-
这里说的QSharedPointer的陷阱,也可能是我的使用不当,不过还是想记录下来,让别人不要踩到同样的坑。
-
先来看我的使用代码:
static void UseSharedPtr(const QSharedPointer<QWidget>& pW)
{
const QSharedPointer<QWidget>& pW2 = pW;
}
void MainWindow::Test1()
{
QWidget* pW = new QWidget(this);
pW->setObjectName("SharedWidget");
UseSharedPtr(QSharedPointer<QWidget>(pW));
qDebug() << pW->objectName();
}
如果调用下面代码,会出现什么情况?
MainWindow w;
w.Test1();
结果是 程序会挂掉!
- 为什么呢?
从源头来看,在上面的代码中,我构造QSharedPointer调用的构造函数,在Qt的官方文档有说:
QSharedPointer::QSharedPointer(X *ptr)
Creates a QSharedPointer that points to ptr. The pointer ptr becomes managed by this QSharedPointer and must not be passed to another QSharedPointer object or deleted outside this object.
Since Qt 5.8, when the last reference to this QSharedPointer gets destroyed, ptr will be deleted by calling X’s destructor (even if X is not the same as QSharedPointer’s template parameter T). Previously, the destructor for T was called.
意思就是我们传给QSharedPointer的指针,它的销毁就会由QSharedPointer管理,而在上面的代码中,我们构造的QSharedPointer只是一个临时变量,当UseSharedPtr执行退出之后,它的引用计数就会变为0,此时就会销毁传入的指针,所以后面再对指针使用就会报错!
- 接下来再做个试验
首先,把UseSharedPtr函数改成模板函数:
template<typename T>
static void UseSharedPtr(const QSharedPointer<T>& pW)
{
const QSharedPointer<T>& pW2 = pW;
}
- 然后如果像下面这样使用,会有问题吗?
void MainWindow::Test2()
{
QString str;
UseSharedPtr<QString>(QSharedPointer<QString>(&str));
}
结果是程序报错!
原因就是QSharedPointer管理的指针必须是在堆上创建的内存,不能是在栈上创建的!
- 结论
所以,虽然说C++没有自动内存回收机制, 而从C++11开始引入智能指针,但对于智能指针的使用还得多注意,不是使用了智能指针就一劳永逸!