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を2回コピーしています(私は?、1回は結果に入れられ、2番目は値で返す場合)。これは避けたかったのです。

4

3 に答える 3

4

deleteLaterドキュメントから:

このオブジェクトの削除をスケジュールします。

コントロールがイベントループに戻ると、オブジェクトは削除されます。この関数が呼び出されたときにイベントループが実行されていない場合(たとえば、QCoreApplication :: exec()の前にオブジェクトでdeleteLater()が呼び出された場合)、イベントループが開始されるとオブジェクトは削除されます。

だからあなたがそこでしていることは安全です。明らかに、永続化される可能性のあるそのオブジェクト(またはそのメンバー)への参照またはポインターを渡すことは間違っています。ただし、コピーを返す場合は問題ありません。

しかし、あなたがしていることは、あなたがしたいことをするかもしれないし、しないかもしれません。readAllブロックせず、現在利用可能なデータを返します。つまり、への1回の呼び出しでreadAll、部分的な応答しか読み取れない可能性があります。ただし、他の方法ですべてのデータが到着したことを確認した場合を除きます。

ドキュメントからのその他の注意事項:

新しいイベントループに出入りする(たとえば、モーダルダイアログを開く)と、遅延削除は実行されないことに注意してください。オブジェクトを削除するには、コントロールはdeleteLater()が呼び出されたイベントループに戻る必要があります。

したがって、このタイプのことを行うときに心配する唯一のことは、何らかの形で「現在の」イベントループに再び入る関数を呼び出すことです。しかし、それが次の方法で行われた場合、それは起こりませんQCoreApplication::processEvents

イベントループなしでこの関数を継続的に呼び出すローカルループを実行している場合、DeferredDeleteイベントは処理されません。

だからそれもカバーされています。遅延削除ロジックはかなり複雑ですが、通常の状況では安全です。Qtの内部を非常に深く掘り下げている場合(またはそこで何か怪しいことをする可能性のあるコードを呼び出している場合)、防御してください。ただし、通常のコードフローの場合、deleteLater持続する可能性のあるぶら下がっている参照(またはポインター)がない限り、安全です。

于 2013-01-12T15:56:50.680 に答える
0

何をしdeleteLaterますか?その名前から、後で削除するオブジェクトを登録することを期待します(トランザクションの終了?セッションの終了?)。その場合、それ以降の時点が発生していない限り、安全に使用できます。唯一の問題は、その時点がいつ発生するかを知ることですが、トランザクションの終了やセッションの終了などの場合は、おそらく安全です。関数がトランザクションまたはセッション内で呼び出された場合、トランザクションまたはセッションは、戻るまで終了しません。

于 2013-01-12T15:54:47.580 に答える
-1

deleteLater安全ですが、まったく使用しない方がいいです。

コントロールがイベントループに戻ると、オブジェクトは削除されます。この関数が呼び出されたときにイベントループが実行されていない場合(たとえば、QCoreApplication :: exec()の前にオブジェクトでdeleteLater()が呼び出された場合)、イベントループが開始されるとオブジェクトは削除されます。

オブジェクトを削除できることを意味しますmmm...決して。これは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();
}

少なくとも、RAIIを使用するのはC++の慣用句ではありません。

他のサイズからすると、コピーオンライトのイデオムを使用するQStringため、コピーは安価な操作です。QSring

于 2013-01-12T16:13:31.760 に答える