使用QNetworkAccessManager时的智能指针,避免了手动内存管理

问题描述 投票:0回答:1

我有以下类,该类调用一些对服务器的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吗?

c++ qt smart-pointers signals-slots qsharedpointer
1个回答
0
投票

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

private:
    class deleteLaterDeletor
    {
    public:
        template<typename T>
        void operator()(T *reply) const
        {
            if(reply) {
                reply->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

© www.soinside.com 2019 - 2024. All rights reserved.