1

我正在考虑这样的写作方法:

QString getData() {
    QNetworkReply *reply = getReply();
    reply->deleteLater();
    return QString::fromUtf8(reply->readAll()).trimmed();
}

安全吗?如果我被迫这样写:

QString getData() {
    QNetworkReply *reply = getReply();
    QString result = QString::fromUtf8(reply->readAll()).trimmed();
    reply->deleteLater();
    return result;
}

我要避免 QString 两次(是吗?,一次将其放入结果中,第二次将其按值返回),这是我想避免的。

4

3 回答 3

4

deleteLater文档中:

计划删除此对象。

当控制返回事件循环时,该对象将被删除。如果调用此函数时事件循环没有运行(例如,在 QCoreApplication::exec() 之前对对象调用 deleteLater()),则一旦启动事件循环,该对象将被删除。

所以你在那里做的事情是安全的。显然,分发可能被持久化的对象(或其成员)的引用或指针是错误的。但是,如果您要退回副本,那很好。

但是你正在做的事情可能会或可能不会做你想做的事情。readAll不阻塞,它返回当前可用的数据。这意味着一次调用readAll可能只会读取部分响应 - 除非您确保所有数据都已通过其他方式到达。

其他需要注意的事情,来自文档:

请注意,进入和离开新的事件循环(例如,通过打开模式对话框)不会执行延迟删除;对于要删除的对象,控件必须返回到调用 deleteLater() 的事件循环。

因此,在做这种事情时唯一需要担心的是调用以某种方式重新进入“当前”事件循环的函数。但如果通过以下方式完成,则不会发生这种情况QCoreApplication::processEvents

如果您正在运行一个连续调用此函数的本地循环,而没有事件循环,则不会处理 DeferredDelete 事件。

所以这也被覆盖了。延迟删除逻辑相当复杂,但在正常情况下是安全的。如果您正在深入研究 Qt 内部结构(或调用可能在那里做一些可疑事情的代码),请保持警惕。但是对于正常的代码流,deleteLater只要您没有可能持续存在的悬空引用(或指针),它就是安全的。

于 2013-01-12T15:56:50.680 回答
0

做什么deleteLater?从它的名字来看,我希望它会在稍后的某个时间点注册要删除的对象(事务结束?会话结束?)。如果是这样,只要没有出现稍后的时间点,您就可以安全地使用它。唯一的问题是知道该点何时发生,但是对于事务结束或会话结束之类的事情,您可能是安全的——如果您的函数是在事务或会话中调用的,则事务或会话在您返回之前不会结束。

于 2013-01-12T15:54:47.580 回答
-1

It is safe, but you'd better not use deleteLater at all, because

The object will be deleted when control returns to the event loop. If the event loop is not running when this function is called (e.g. deleteLater() is called on an object before QCoreApplication::exec()), the object will be deleted once the event loop is started.

means that object can be deleted mmm... never. This pretend to work like GC, but it is even worse:

class A: public QObject
{
    char x[10000000];
};

void process()
{
    A* a = new A();
    //delete a;
    a->deleteLater();
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    for (int k = 0; k < 1000000; ++k) {
        process();
    }
    return a.exec();
}

At least it is not C++ idiomatic, that uses RAII.

From the other size, copying QString is a cheap operation, because QSring uses copy-on-write ideome.

于 2013-01-12T16:13:31.760 回答