【问题标题】:How do I initialize a std::unique_ptr with a deleter in a constructor?如何在构造函数中使用删除器初始化 std::unique_ptr?
【发布时间】:2021-02-05 01:46:12
【问题描述】:

我正在尝试将 C 库原始指针包装在 std::unique_ptr 中,并使用带有 Deleter 的构造函数来调用库释放函数。为了设置原始指针,我必须在构造函数中进行一些设置,因此我无法在初始化列表中构造 unique_ptr。

.h

class Resampler {

public:
    Resampler(unsigned int baseSamplerate, unsigned int channels);
  
private:
    std::unique_ptr<SwrContext, decltype(&swr_free)> context{nullptr, nullptr};
};

.cpp

Resampler::Resampler(unsigned int baseSamplerate, unsigned int channels) : baseSamplerate(baseSamplerate), ratio(1.0), channels(channels) {

    int64_t channelLayout;
     ..

    SwrContext *ctx = swr_alloc_set_opts(nullptr,
                                         channelLayout,
                                         AV_SAMPLE_FMT_FLTP,
                                         baseSamplerate,
                                         channelLayout,
                                         AV_SAMPLE_FMT_FLTP,
                                         baseSamplerate,
                                         0,
                                         nullptr);

    context = std::unique_ptr<SwrContext, decltype(&swr_free)>(ctx, &swr_free);
    setRatio(1.0);
}

这不会在 IDE 中产生错误,但编译器会报错:

> error: cannot initialize a parameter of type 'SwrContext **' with an
> lvalue of type 'std::__ndk1::unique_ptr<SwrContext, void
> (*)(SwrContext **)>::pointer' (aka 'SwrContext *')
std::unique_ptr<SwrContext, decltype(&swr_free)> context{ nullptr };

std::unique_ptr<SwrContext, decltype(&swr_free)> context{};

不是有效的构造函数,并且

std::unique_ptr<SwrContext, decltype(&swr_free)> context;

生产

错误:'Resampler' 的构造函数必须显式初始化 没有默认构造函数的成员“上下文”

那么有没有办法做到这一点,还是我应该将上下文设为原始指针并手动管理?

【问题讨论】:

    标签: c++ c++17


    【解决方案1】:

    std::unique_ptr&lt;T&gt; 的删除器在这种情况下必须是可调用对象。尝试像这样使用 仿函数

    struct swr_deleter
    {
        void operator()(SwrContext* context)
        {
            if (context != nullptr)
            {
                swr_free(context);
            }
        }
    }
    

    那么您的std::unique_ptr 将如下所示:

    std::unique_ptr<SwrContext, swr_deleter> context;
    

    【讨论】:

    • 这让我可以让它工作。我认为问题是因为 sw_free 需要 ** 而不是 *。所以在我的情况下,我需要做 `swr_free(&context);'。我认为这可能是我原来的方式行不通。
    • "std::unique_ptr&lt;T&gt; 的删除器必须是可调用对象" - 独立函数也可用作删除器。只是不是在这种特殊情况下,因为swr_free() 的签名与删除器的要求不兼容,因为它需要SwrContext** 而不是SwrContext*。使用仿函数可以解决这个问题
    猜你喜欢
    • 2013-10-14
    • 2016-05-03
    • 1970-01-01
    • 2016-05-07
    • 2020-04-17
    • 1970-01-01
    • 2015-09-04
    • 1970-01-01
    • 2021-08-23
    相关资源
    最近更新 更多