C++ 在调用delete later的对象上工作是否安全

C++ 在调用delete later的对象上工作是否安全,c++,qt,C++,Qt,我在考虑这样的写作方法: QString getData() { QNetworkReply *reply = getReply(); reply->deleteLater(); return QString::fromUtf8(reply->readAll()).trimmed(); } QString getData() { QNetworkReply *reply = getReply(); QString result = QStri

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

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 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两次(是吗?),一次放入结果,第二次按值返回),这是我想要避免的。

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

来自文档:

计划删除此对象

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

所以你在那里做的是安全的。显然,向可能被持久化的对象(或其成员)分发引用或指针是错误的。但如果你还书,你就没事了

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

文档中需要注意的其他事项:

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

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

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


这也包括在内。延迟删除逻辑相当复杂,但在正常情况下是安全的。如果您正在深入挖掘Qt内部(或者调用可能有可疑之处的代码),请采取防御措施。但是对于正常的代码流,
deleteLater
是安全的,只要您没有可能持续存在的悬空引用(或指针)。

是安全的,但是您最好不要使用
deleteLater
,因为

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

意味着对象可以被删除嗯。。。从未。这假装像GC一样工作,但更糟糕的是:

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();
}
A类:公共QObject
{
字符x[10000000];
};
无效过程()
{
A*A=新的A();
//删除一条;
a->deleteLater();
}
int main(int argc,char*argv[])
{
qcorea应用程序(argc、argv);
对于(整数k=0;k<1000000;++k){
过程();
}
返回a.exec();
}
<>至少使用C++语言是不习惯的,使用RII.<
从另一个角度来看,复制
QString
是一种廉价的操作,因为
QString
使用写时复制的ideome。

删除以后的
deleteLater
如何工作?@sftrabbit他在使用Qt,所以他不是定义方法的人。@AntonieBlom啊,我没有注意到。谢谢。
deleteLater
QObject
的成员函数。您误读了文档。在
a
中粘贴一个析构函数以输出某些内容,您将看到它在
exec
启动时被调用。引用:“一旦事件循环启动,对象将被删除。”@Mat,此示例将在执行
a.exec
之前生成错误的alloc。这是一个语法示例,但在单个事件循环中存在累积挂起对象(和挂起资源)的问题。“意外完成事件处理”(例如,使用
QTHread
)的问题也存在。请确保在某些情况下可能会出现问题。不过,你的样本并没有证明这一点。如果您认为代码消亡是
deleteLater
中的一个bug,那么事实并非如此,而是错误地使用了它。它的行为如文档所示。@Mat,我并不是说
deleteLater
中有一些bug,但使用
deleteLater
时经常会有异味。@Lol4t0这是事务处理中的经典模式;在这种情况下,QT只是将事件循环当作一个事务来处理(仔细想想,这很有意义)。