介绍 QScopedPointer
by Harald Fernengel on August 21,2009
翻译:wangjieest
第一次翻译,请多见谅。
Qt usually takes the boring memory allocation and deallocation from you, either through its implicitly shared containers, or with QObject’s parent child relationship model.
But every once in a while, we need to allocate something on the heap, and then the stress starts – where do we delete it, and how do we make sure to not leak the memory?
通常Qt从C++开发者手里接管了枯燥无味的垃圾回收工作,例如通过Qt自身的隐式共享,或者用QObject父子关系模型。
但是,每一次我们需要在堆上分配内存的时候,就有压力了 —— 我们需要在哪儿删除它,我们如何确保不会有内存泄露?
To fix this problem, QScopedPointer was born.
It will delete the object it is pointing to automatically when it goes out of scope:
为了解决这个问题,QScopedPointer 诞生了。
当要超出作用域时,QScopedPointer 便会自动的删除它所指向的对象(的内存):
void foo()
{
QScopedPointer<int> i(newint(42));
//…
if (someCondition)
return;
// 我们在堆上分配的一个整数将在这个位置,
// …
} // 或者这个位置被自动的删除
A new exit condition in our function will not make it leak the integer that we allocated.
在我们函数中,一个新的出口条件,将会使我们分配的内存不会泄露!(真心不会翻)
So how do we access the object that we are pointing to?
QScopedPointer implements operator* and operator->, so you it can be accessed just like any other pointer:
那么,我们该如何访问和使用 QScopedPointer所指向的对象呢?
QScopedPointer已经实现了 operator * 和 operator ->操作符重载,所以,就像普通指针一样的去用它吧:
QScopedPointer<int> i(newint(42));
*i = 43;
*i = 43;
Some operators are missing by design, for example the assignment operator:
一些常有的操作(操作符重载),在设计上是有意没有实现,例如 赋值运算符( = );
QScopedPointer<int> i(newint(42));
i = newint(43);// 错误
i.reset(new int(43)); // 正确
i = newint(43);// 错误
i.reset(new int(43)); // 正确
We figured that “reset” looks scary enough to make the reader realize that the old object is deleted, and the QScopedPointer is now pointing to the new object.
我们设想:"reset" 看起来足够吓人了,以致于能够使读者认识到,这样会删除旧的对象,并使QScopedPointer指向新的对象.
Another operator that is missing by design is the operator T*() that would allow accessing the pointer directly.This prevents accidents like:
另一个在设计时就没打算实现的操作符是 T*(),那将导致直接访问我们的指针而不是指针管理的对象。这是用来阻止如下的情况:
int*foo()
{
QScopedPointer<int> i(newint(42));
//…
return i; // thankfully, this does not compile.
}
{
QScopedPointer<int> i(newint(42));
//…
return i; // thankfully, this does not compile.
}
Do you see the mistake?
The moment we return, our object will be deleted, because the scoped pointer goes out of scope.
We would return a dangling pointer, potentially leading to a nasty crash. However, we can tell QScopedPointer that its job is done and that we take ownership of the heap object by calling take(). Our function might look like this:
你有看到错误没?
在函数返回的同时,我们的对象会被删除,因为QscopedPointer离开其作用域了.
我们将会返回一个悬垂指针,有可能导致程序崩溃。然后,当我们可以通过调用take()成员函数,告诉QScopedPointer它的工作完成了,从而接手它所指向的堆的控制权,我们的函数可能会像如下这样:
int*foo()
{
QScopedPointer<int> i(newint(42));
…
if (someError)
return 0; // our integer is deleted here
return i.take(); // from now on, our heap object is on its own.
}
{
QScopedPointer<int> i(newint(42));
…
if (someError)
return 0; // our integer is deleted here
return i.take(); // from now on, our heap object is on its own.
}
But what about memory allocated with malloc, or the operator new[] for arrays?
For those cases, we introduced a second template parameter to QScopedPointer that defines the cleanup:
但是如果是通过malloc分配的内存,或者通过 new[] 分配的数组呢?
对于这种情况,我们为QScopedPointer引进了第二个模板参数来定义其清理工作:
QScopedPointer<int, QScopedPointerPodDeleter> pod(static_cast<int*>(malloc(sizeofint)));
QScopedPointerPodDeleter (pod stands for “plain old data”) will call free on the object if our QScopedPointer goes out of scope.
For convenience, there is a QScopedArrayPointer that defaults to deleting the object it is pointing to with the delete[] operator.
It also features operator[] for convenience, so we can write:
当我们的QScopedPointer超出其作用域时,QScopedPointerPodDeleter(pod意为普通的旧数据(plain old data))将会为其指向的对象调用free()函数.
为方便起见,我们用一个QScopedArrayPointer来指向那些需要被delete[]删除的对象。
同样为了方便,它还具有operator [] 运算符重载(取数组成员) ,所以我们可以这样写:
void foo()
{
QScopedArrayPointer<int> i(newint[10]);
i[2] = 42;
…
return; // our integer array is now deleted using delete[]
}
{
QScopedArrayPointer<int> i(newint[10]);
i[2] = 42;
…
return; // our integer array is now deleted using delete[]
}
Note that if you have a reference counted object, you can use QExplicitlySharedDataPointer to ensure that an object is deleted correctly when its reference count goes to 0.
注意:如果你需要管理那些采用了引用计数技术的对象,那么你可以使用 QExplicitlyShareDataPointer 来管理这些对象,让其在引用计数变为0时,保证对象的正确删除。
QScopedPointer and QExplicitlySharedDataPointer are already used all over the place in the Qt for S60 branch and will soon hit Qt’s master branch.
And the best part is that with the introduction of these smart pointers, we could remove lots of boring code and make Qt more readable without adding overhead – since all functions are inlined, the resulting binary using QScopedPointer is identical to the manual new/delete approach.
QScopedPointer 和 QExplicitlySharedDataPointer 已经被用于Qt开发S60分支的各个地方,很快的,它将进入Qt的主开发分支。
最大的亮点就是,Qt对这些智能指针的引入可使我们能够移除很多乏味的代码,并在不增加开销的情况下使Qt更具可读性——因为所有函数被内联实现的同时,在使用QScopedPointer管理内存而生成的二进制文件和手工new/delete方法是一样的.
Happy developing
用Qt的智能指针快乐的开发下去吧。
相关推荐
【Qt智能指针QScopedPointer】是Qt框架中用于管理动态分配对象的一种智能指针,类似于C++标准库中的std::unique_ptr。QScopedPointer确保动态创建的对象在作用域结束时会被正确删除,从而避免内存泄漏。其核心特点是...
压缩包内包含msvc和mingw64两个版本的openssl...或者使用 qInfo() << QScopedPointer(new QNetworkAccessManager)->supportedSchemes(); 输出 ("ftp", "file", "qrc", "http", "https", "data"),有https也说明生效了。
在Qt框架中,提供了多种智能指针类型,如QPointer、QSharedPointer、QScopedPointer、QWeakPointer等,它们能够帮助开发者更安全地处理内存管理,防止常见的内存泄漏和野指针问题。 【QSharedPointer】是Qt中一个...
QScopedPointer<Ui_Widget> ui; }; #endif // WIDGET_H ``` 通过以上步骤,你已经在Qt项目中成功集成了`spdlog`,并学会了如何使用它来记录日志。这只是一个基础示例,实际项目中你可以根据需求定制更多的日志...
在QT中,可以使用QScopedPointer或QSharedPointer等智能指针来自动管理内存。 项目的"MyDemo"部分可能是实际的示例代码,展示了如何在QT应用程序中集成上述单例设计模式和相关技术。通过分析和理解这部分代码,...
- 提供了QScopedPointer、QSharedDataPointer等用于智能指针管理的类。 理解这些类和模块的继承关系,有助于开发者在使用Qt5进行软件开发时,快速定位到合适的类和方法,从而构建出功能丰富且高效的软件应用。此外...
例如,使用RAII(Resource Acquisition Is Initialization)风格的智能指针,如`QScopedPointer`,可以确保文件在不再需要时自动关闭,防止资源泄露。 总的来说,QT通过提供方便的API,使得开发者能够轻松地在跨...
- QScopedPointer和QSharedPointer:用于自动管理动态分配对象的生命周期,防止内存泄漏。 8. Qt定时器(Timers) - QTimer:基于时间的事件,可以定时执行代码。 9. Qt JSON支持 - 提供了操作JSON数据的类,如...
4. **避免过度使用`new`**:尽量减少手动`new`操作,利用Qt提供的智能指针或其他内存管理工具,如`QScopedPointer`和`QSharedPointer`等,这些工具能够自动管理对象的生命周期,减少内存泄露的风险。 #### 实例分析...
QScopedPointer<QUdpSocket> socket(new QUdpSocket); if (!socket->bind(QHostAddress::AnyIPv4, 12345)) { qCritical() << "Failed to bind the UDP socket:" << socket->errorString(); return; } } ``` 3....