簡體   English   中英

使用 QNetworkAccessManager 時智能指針和避免手動 memory 管理

[英]Smart pointers and avoid manual memory management when using QNetworkAccessManager

我有以下 class 調用一些 HTTP API 請求到服務器:

class NetworkRequest : public QObject {

public:
    NetworkRequest(QNetworkAccessManager* netManager):
        m_netManager(netManager){}

    void send(QUrl const &url){
        QNetworkRequest request(url);
        auto reply = m_netManager->get(request);
        connect(reply, &QNetworkReply::finished, [this, reply](){
            // do some stuff with reply (like if url is redirected)
            if(isRedirected(reply)){
                // we have to delete the reply and send a new one
                QUrl newUrl;
                // somehow get the new url;
                reply->deleteLater();
                send(newUrl);
            }
            else{
                reply->setParent(this); // so that it will be deleted when an instance of this class is deleted
                emit completed(reply);
            }
        });
    }

signals:
    void completed(QNetworkReply* reply);

private:
    QNetworkAccessManager* m_netManager;
    bool isRedirected(QNetworkReply * reply){
        bool yes = false;

        /* process the process reply and determine yes is true or false
        ....
        **/
        return yes;
    }
};

我以這種方式使用 class:

auto req = new NetworkRequest(nm);
req->send("http://someurl.com");
connect(req, &NetworkRequest::completed, randomClass, &RandomClass::slot);

// in RandomClass::slot I call NetworkRequest::deleteLater() when I finished with the network data

現在這顯然涉及一些手動 memory 管理,我必須小心不要忘記刪除原始指針。 我想知道是否可以使用QSharedPointer (甚至std::shared_ptr )編寫上面的代碼並替換:

        auto reply = m_netManager->get(request);

和:

        auto smartReply = QSharedPointer<QNetworkReply>(m_netManager->get(request));

然后用smartReply.get()替換所有reply實例,然后忘記手動刪除回復對象。 但是,我不清楚共享指針是否會自動刪除對象,因為在我調用send()的時間范圍和信號QNetworkReply::finished之間,智能指針會知道原始指針仍在使用中嗎? 另外,當我刪除NetworkRequest的實例時,共享指針會自動刪除它擁有的QNetworkReply嗎?

好的,經過一番思考,我想出了一個解決方案。 我想解決的主要問題是避免手動刪除我的QNetworkReply* object,而是希望在刪除NetworkRequest實例時自動銷毀它。 In order to achieve this, I used a std::unique_ptr as a private member of my NetworkRequest class so when the class is destroyed, the unique_ptr automatically cleans the object in memory. Furthermore, by default std::unique_ptr deletes the object it hold upon reassignment, so whenever I call the send function in my, I can assign a new object to the smart pointer and the previous object in memory will get deleted automatically. 需要注意的一件事是,Qt 文檔建議使用QObject::deleteLater()刪除QNetworkReply* (我不完全清楚為什么會這樣),為了做到這一點,可以使用自定義刪除器. 所以在我的代碼中,我聲明了一個私有成員,如下所示:

private:
    struct deleteLaterDeletor
    {
        void operator()(QObject *object) const
        {
            if(object) {
                object->deleteLater();
            }
        }
    };

    using ReplyPointer = std::unique_ptr<QNetworkReply, deleteLaterDeletor>;

    ReplyPointer m_reply;

然后在我send function 中:

        m_reply = ReplyPointer(mNetManager->get(netRequest));

顯然,在信號和槽的簽名中,我必須傳遞原始指針( m_reply.get() )。

QSharedPointer也可以用來代替std::unique_ptr

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM