将 unique_ptr 与 GError 的自定义删除器一起使用

using unique_ptr with custom deleter for GError

将 unique_ptr 与 c 函数的自定义删除器一起使用 return ptr 非常简单,但我如何将它用于将 ptr 的 ptr 作为参数的函数(如 GError)

我在几个案例中遇到过这种情况,但没有找到一种直接的方法来做到这一点。我错过了什么吗?

using Element = std::unique_ptr<GstElement, void (*)(GstElement*)>;
using Error = std::unique_ptr<GError, void (*)(GError*)>;
...
GError* plain_err;
Element pipeline(gst_parse_launch(str, &plain_err), object_unref); // ok

Error uniq_err {nullptr, error_free};
Element pipeline(gst_parse_launch(str, &(uniq_err.get())), object_unref); // error: lvalue required as unary ‘&’ operand

我能想到的唯一方法就是稍后分配

GError* plain_err;
Element pipeline(gst_parse_launch(str, &plain_err), object_unref);
Error uniq_err {plain_err, error_free};
plain_error = nullptr;

您的这部分代码:

GError* plain_err;
Element pipeline(gst_parse_launch(str, &plain_err), object_unref);

建议gst_parse_launch()分配GError*和returns。在这种情况下,您不能按自己的方式使用 unique_ptr。因为 unique_ptr 只是管理指针的生命周期。

您可以尝试使用 unique_ptr:

来管理您的指针
struct ErrorRelease {
    void operator()(GError* ptr) {
        // release pointer
    }
};
using Error = std::unique_ptr<GError, ErrorRelease>;

GError* plain_err;
Element pipeline(gst_parse_launch(str, &plain_err), object_unref);

Error uniq_err(plain_err);

在此之后,您必须记住不要手动释放 plain_err,因为它是由您的 unique_ptr 管理的。给它赋另一个值是可以的,只是不要手动释放它。

我发现从 lambda 返回一个元组稍微好一点,

auto [pipeline, err] = [&]() noexcept {
    GError* err = nullptr;
    auto* pipeline = gst_parse_launch(str, &err);
    return std::tuple{Element{pipeline, object_unref}, Error{err, error_free}};
}();