【问题标题】:Alternative to deleting raw pointer in C++ Qt在 C++ Qt 中删除原始指针的替代方法
【发布时间】:2019-12-20 05:53:41
【问题描述】:

所以我有以下用 Qt C++ 编写的代码:

// Post* derives from QObject
Post* post = new Post(this);
QString url;

ParseResult result = parse(url, post); // this function takes a Post* and modifies it

// if result is succesfully parsed
if(result == ParseResult::Success){
    // add the post to a std::vector<Post*> which is a member of the class
}
else{
    post->deleteLater();
}

现在你可以看到我正在删除原始指针Post*,但是我想知道我上面的内容是否可以以不需要使用deleteLater()的另一种方式实现。

【问题讨论】:

  • 智能指针算作答案吗?
  • @nada 不支持 Qt。您可以获得双重删除(一次由智能指针,一次由 QObject 的父级。)
  • 那么我的答案是:修复 Qt 以兼容智能指针,然后使用智能指针
  • @AlanBirtles 这被认为是过度设计,至少由这个答案的作者 - Why don't the official Qt examples and tutorials use smart pointers?
  • @JonnyHenly 您链接到的答案没有抓住重点。智能指针不仅仅与泄漏有关。它们还涉及异常安全和减少出错的可能性。以“Qt 方式”进行操作需要您正确操作。但我们是人类,所以我们会犯错误。如果你犯了一个错误,你可能会泄漏(例如,你分配了一个没有父对象的对象,但是在分配和你为其分配父对象的点之间发生了一些事情,你退出了范围。)使用智能指针,这样的错误更多困难,因此错误的空间较小。

标签: c++ qt pointers qobject


【解决方案1】:

如果post 不会比this 活得更久,并且总是将成为this 的子级(意味着它永远不会重新成为父级),那么您可以将实例存储在vectorunique_ptr&lt;Post&gt;:

class This: /* ... */ {
// ...
    std::vector<std::unique_ptr<Post>> post_vec_;
};

现在您的代码可以省略删除:

auto post = std::make_unique<Post>(this);
QString url;

ParseResult result = parse(url, post.get());
if (result == ParseResult::Success) {
    post_vec_.push_back(std::move(post));
    // 'post' was moved from, so it's just a nullptr now.
}

// No 'else' needed. 'post' is going to be deleted when it goes out of scope.

(这假设 post-&gt;deleteLater() 在您的原始代码中可能已替换为 delete post。您似乎没有理由使用 deleteLater() 而不仅仅是直接调用 delete。)

this被销毁时,它的成员将在调用基类析构函数之前首先被销毁。所以post_vec_ 将首先被销毁,这意味着它包含的智能指针将删除它们管理的Post 对象。这些对象的析构函数将从其父对象注销对象,因此不会发生双重删除。这就是为什么这个答案要求这些对象不能超过 this 并且不能被重新设置。

最后一点,如果您不想在 This 标头中公开 Post 类,您可以转发声明它:

class Post;

class This: /* ... */ {
// ...
    std::vector<std::unique_ptr<Post>> post_vec_;
};

unique_ptr 仍然可以使用它,只要你在.cpp 文件中实现你的析构函数。如果没有析构函数,那么可以使用默认的,但是需要在.cpp文件中默认:

class Post;

class This: /* ... */ {
public:
    // ...
    ~This() override;

// ...
    std::vector<std::unique_ptr<Post>> post_vec_;
};

.cpp 文件中:

This::~This() = default;

【讨论】:

  • 如果你在智能指针中使用QObject,最好使用QPointer而不是std::unique_ptr
  • @SerhiyKulish QPointer 不会自动删除托管对象,这正是 OP 想要的。当其他人删除对象时,它只是将自己设置为 null。见:doc.qt.io/qt-5/qpointer.html#dtor.QPointer
猜你喜欢
  • 2021-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多