[英]Smart pointers and avoid manual memory management when using QNetworkAccessManager
I have the following class which calls some HTTP API request to a server:我有以下 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;
}
};
I use the class in this way:我以这种方式使用 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
Now this clearly involves some manual memory management and I have to be careful to not forget deleting the raw pointers.现在这显然涉及一些手动 memory 管理,我必须小心不要忘记删除原始指针。 I was wondering if the code above could be written using
QSharedPointer
(or even std::shared_ptr
) and replacing:我想知道是否可以使用
QSharedPointer
(甚至std::shared_ptr
)编写上面的代码并替换:
auto reply = m_netManager->get(request);
with:和:
auto smartReply = QSharedPointer<QNetworkReply>(m_netManager->get(request));
then replace all instances of reply
with smartReply.get()
and then forget about manually deleting reply objects.然后用
smartReply.get()
替换所有reply
实例,然后忘记手动删除回复对象。 However, it is unclear to me if the shared pointer will automatically delete the objects because between the time frame that I call send()
and the signal QNetworkReply::finished
, would the smart pointer know that the raw pointer is still in use?但是,我不清楚共享指针是否会自动删除对象,因为在我调用
send()
的时间范围和信号QNetworkReply::finished
之间,智能指针会知道原始指针仍在使用中吗? Also when I delete an instance of NetworkRequest
will the shared pointer automatically delete the QNetworkReply
it owns?另外,当我删除
NetworkRequest
的实例时,共享指针会自动删除它拥有的QNetworkReply
吗?
Ok so after some thinking I came up with a solution.好的,经过一番思考,我想出了一个解决方案。 The main problem I wanted to solve was to avoid deleting my
QNetworkReply*
object manually, instead I wanted it to be automatically destroyed when an instance of NetworkRequest
is deleted.我想解决的主要问题是避免手动删除我的
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. 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. 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. One thing to notice, was the Qt docs recommend that QNetworkReply*
should be deleted using QObject::deleteLater()
(it is not fully clear to me why this is the case), in order to do this one can just use a custom deleter.需要注意的一件事是,Qt 文档建议使用
QObject::deleteLater()
删除QNetworkReply*
(我不完全清楚为什么会这样),为了做到这一点,可以使用自定义删除器. So in my code, I declared a private member as following:所以在我的代码中,我声明了一个私有成员,如下所示:
private:
struct deleteLaterDeletor
{
void operator()(QObject *object) const
{
if(object) {
object->deleteLater();
}
}
};
using ReplyPointer = std::unique_ptr<QNetworkReply, deleteLaterDeletor>;
ReplyPointer m_reply;
Then in my send
function:然后在我
send
function 中:
m_reply = ReplyPointer(mNetManager->get(netRequest));
Obviously, in the signature of signal and slots I have to pass the raw pointer ( m_reply.get()
).显然,在信号和槽的签名中,我必须传递原始指针(
m_reply.get()
)。
( QSharedPointer
can also be used instead of std::unique_ptr
) (
QSharedPointer
也可以用来代替std::unique_ptr
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.