如何在构造函数中使用删除器初始化 std::unique_ptr?

Posted

技术标签:

【中文标题】如何在构造函数中使用删除器初始化 std::unique_ptr?【英文标题】:How do I initialize a std::unique_ptr with a deleter in a constructor? 【发布时间】: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)> contextnullptr, 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' 的构造函数必须显式初始化 没有默认构造函数的成员“上下文”

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

【问题讨论】:

【参考方案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*。使用仿函数可以解决这个问题

以上是关于如何在构造函数中使用删除器初始化 std::unique_ptr?的主要内容,如果未能解决你的问题,请参考以下文章

在构造函数中定义状态还是使用属性初始化器更好?

在构造函数中定义状态还是使用属性初始化器更好?

在构造函数初始化器列表中初始化函数指针数组 - 错误

Vue Prop 没有初始化器,也没有在构造函数中明确赋值

属性 '...' 没有初始化器,也没有在构造函数中明确分配

谁删除了在构造函数中有异常的“新”操作期间分配的内存?