使用unique_ptr和自定义删除器混淆

时间:2015-02-19 14:54:53

标签: c++ c++11 unique-ptr

我尝试将unique_ptr用于SDL_Surface类型的自定义删除工具。这只是使用int类型的示例,但我希望您明白这一点。

#include <iostream>
#include <functional>
#include <memory>

typedef int SDL_Surface;


SDL_Surface * CreateSurface()
{
    SDL_Surface * p = new SDL_Surface;
    return p;
}

void FreeSurface(SDL_Surface *p)
{
    delete p;
}

int main() {
    std::unique_ptr<SDL_Surface, std::function< void (SDL_Surface *) > > uptr_1; 

    //how to assign a value to uptr_1 and the deleter? 

    return 0;
}

uptr_1是否已正确声明并初始化为nullptr?如果是这样,我如何分配指针和删除功能?

我该怎么封装呢: 带有删除器的std::unique_ptr< SDL_Surface, std::function< void (SDL_Surface *) > >并不总是在我想要的每个SDL_Surface上写一行,另一个是typedef?

我刚刚开始学习C ++ 11的功能,这对我来说很难。

3 个答案:

答案 0 :(得分:11)

您可以使用指针和删除器初始化unique_ptr,或者如果稍后重新分配,则可以正常使用=

std::unique_ptr<SDL_Surface, std::function<void (SDL_Surface *)>> uptr_1(CreateSurface(), &FreeSurface);

uptr_1 = std::unique_ptr<SDL_Surface, std::function<void (SDL_Surface *)>>(CreateSurface(), &FreeSurface);

有关详细信息,请参阅suitable docs

要缩短long类型,您确实可以使用类型别名(typedefusing):

typedef std::unique_ptr<SDL_Surface, void (*)(SDL_Surface*)> Surface_ptr;

//or

using Surface_ptr = std::unique_ptr<SDL_Surface, void (*)(SDL_Surface*)>;

注意我实际上已将void (*)(SDL_Surface*)用于删除器类型。如果你知道你总是传递一个实际函数(或无状态lambda),那么就没有理由拖入std::function,因为类型擦除会产生一些开销。

此外,您可以通过为删除器创建默认构造函子来进一步缩短它:

struct FreeSurface_Functor
{
  void operator() (SDL_Surface *s) const
  {
    FreeSurface(s);
  }
};

这样,您可以指定指针std::unique_ptr<SDL_Surface, FreeSurface_Functor>的类型(可能是别名),而不必提供删除器;它将是默认构造的:

std::unique_ptr<SDL_Surface, FreeSurface_Functor> uptr_1(CreateSurface());

答案 1 :(得分:2)

我会选择decltype

std::unique_ptr<SDL_Surface, decltype(&FreeSurface)> uptr_1(
          CreateSurface(),
          FreeSurface
);

答案 2 :(得分:1)

  

uptr_1是否正确声明并初始化为nullptr

是的,默认构造的unique_ptr将引用null。

  

如果是这样,我该如何分配指针和删除函数?

您应该使用参数构建unique_ptr

 std::unique_ptr<SDL_Surface, std::function< void (SDL_Surface *) > > uptr_1{CreateSurface(), FreeSurface};

或者,在默认构造之后,您可以使用带有临时

的移动分配
uptr_1 = std::unique_ptr<SDL_Surface, std::function< void (SDL_Surface *) > >{CreateSurface(), FreeSurface};

正如您自己建议的那样,类型别名可以提供帮助

using SDL_Uptr = std::unique_ptr<SDL_Surface, std::function< void (SDL_Surface *)>>;
SDL_Uptr  uptr_1;
uptr_1 = SDL_Uptr{CreateSurface(), FreeSurface};

一个中间函数可以帮助简化它,如果它变得重复(如果你做了很多它可能会这样)。

std::unique_ptr<SDL_Surface, void (*)(SDL_Surface *)>
make_sdl_ptr() {
    return std::unique_ptr<SDL_Surface, void (*)(SDL_Surface *)>{CreateSurface(), FreeSurface};
}

然后,您可以使用auto uptr = make_sdl_ptr();

调用此方法

Angew用DefaultConstructible删除器调用你的函数的答案也是一个非常好的解决方案。