0

我有以下类调用一些 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;
    }
};

我以这种方式使用该类:

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

现在这显然涉及一些手动内存管理,我必须小心不要忘记删除原始指针。我想知道上面的代码是否可以使用QSharedPointer (甚至std::shared_ptr)编写并替换:

        auto reply = m_netManager->get(request);

和:

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

然后替换所有实例,reply然后smartReply.get()忘记手动删除回复对象。但是,我不清楚共享指针是否会自动删除对象,因为在我调用的时间范围send()和信号之间QNetworkReply::finished,智能指针会知道原始指针仍在使用中吗?另外,当我删除一个实例时NetworkRequest,共享指针会自动删除QNetworkReply它拥有的吗?

4

1 回答 1

0

好的,经过一番思考,我想出了一个解决方案。我想解决的主要问题是避免QNetworkReply*手动删除我的对象,而是希望在删除实例时自动销毁它NetworkRequest。为了实现这一点,我使用 astd::unique_ptr作为我NetworkRequest的类的私有成员,因此当类被销毁时,会unique_ptr自动清理内存中的对象。此外,默认情况下std::unique_ptr会在重新分配时删除它持有的对象,因此每当我在我的函数中调用该send函数时,我都可以将一个新对象分配给智能指针,并且内存中的前一个对象将被自动删除。需要注意的一件事是,Qt 文档建议QNetworkReply*应该使用删除QObject::deleteLater()(我不完全清楚为什么会这样),为了做到这一点,可以使用自定义删除器。所以在我的代码中,我声明了一个私有成员,如下所示:

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

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

    ReplyPointer m_reply;

然后在我的send函数中:

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

显然,在信号和插槽的签名中,我必须传递原始指针 ( m_reply.get())。

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

于 2019-10-02T15:36:05.050 回答