在 C++ Qt 中删除原始指针的替代方法

Alternative to deleting raw pointer in C++ Qt

所以我有以下用 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() 的方式实现.

如果 post 不会比 this 长寿,并且 总是 将成为 this 的 child (这意味着它永远不会重新设置)然后你可以将实例存储在 unique_ptr<Post>:

vector
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->deleteLater() 可以在您的原始代码中替换为 delete post。您似乎没有理由使用 deleteLater() 而不是仅仅调用delete直接。)

this被销毁时,它的成员将在调用基础class析构函数之前先被销毁。所以 post_vec_ 将首先被销毁,这意味着它包含的智能指针将删除它们管理的 Post objects。那些 objects 的析构函数将从它们的 parents 中注销 objects,因此不会发生 double-deletion。这就是为什么这个答案要求这些 objects 不能比 this 长寿并且不能重新成为父母。

最后一点,如果你不想在 This header 中公开 Post class,你可以直接声明它:

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;