简体   繁体   English

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

[英]Confused using unique_ptr and a custom deleter

I'm trying to use unique_ptr with a custom deleter for SDL_Surface type. 我正在尝试将unique_ptrSDL_Surface类型的自定义删除器一起使用。 This is only an example using int type, but I hope you get the idea. 这只是使用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;
}

Is uptr_1 correctly declared and initialized to nullptr ? uptr_1是否正确声明并初始化为nullptr If so, how can I assign the pointer and the deleter function? 如果是这样,我如何分配指针和删除功能?

And how can I encapsulate this: std::unique_ptr< SDL_Surface, std::function< void (SDL_Surface *) > > with the deleter to not always write that line on every SDL_Surface I want, another typedef? 我怎么能封装这个: std::unique_ptr< SDL_Surface, std::function< void (SDL_Surface *) > > >>>删除器并不总是在我想要的每个SDL_Surface上写那行,另一个是typedef?

I'm just starting to learn C++11 features and this is a hard one for me. 我刚开始学习C ++ 11的功能,这对我来说很难。

You can initialise the unique_ptr with a pointer and deleter, or use = normally if re-assigning later: 您可以使用指针和删除器初始化unique_ptr ,或者如果稍后重新分配则使用= normal:

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);

Refer to suitable docs for details. 有关详细信息,请参阅合适的文档

To shorten the long type, you can indeed use a type alias ( typedef or using ): 要缩短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*)>;

Notice I've actually used void (*)(SDL_Surface*) for the deleter type. 注意我实际上使用了void (*)(SDL_Surface*)作为删除器类型。 If you know you'll always pass an actual function (or stateless lambda) in, there's no reason to drag in std::function , which has some overhead due to type erasure. 如果你知道你总是会传递一个实际函数(或无状态lambda),那么就没有理由拖入std::function ,因为类型擦除会产生一些开销。

Also, you can shorten it even further by creating a default-constructible functor for the deleter: 此外,您可以通过为删除器创建默认构造函子来进一步缩短它:

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

That way, you can make the type of your pointer std::unique_ptr<SDL_Surface, FreeSurface_Functor> (possibly aliased) and you don't have to provide the deleter; 这样,您可以使指针的类型为std::unique_ptr<SDL_Surface, FreeSurface_Functor> (可能是别名),您不必提供删除器; it will be default-constructed: 它将是默认构造的:

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

I would go with decltype : 我会选择decltype

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

Is uptr_1 correctly declared and initialized to nullptr uptr_1是否正确声明并初始化为nullptr

Yes, a default constructed unique_ptr will refer to null. 是的,默认构造的unique_ptr将引用null。

if so, how can I assign the pointer and the deleter function? 如果是这样,我如何分配指针和删除功能?

You should be constructing the unique_ptr with arguments 您应该使用参数构造unique_ptr

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

Alternatively, after the default construction you could use move assignment with a temporary 或者,在默认构造之后,您可以使用临时移动分配

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

As you've suggested yourself, a type alias can help 正如您自己建议的那样,类型别名可以提供帮助

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

An intermediate function could help simplify this if it becomes repetitive (which it probably will if you make a lot of them). 一个中间函数可以帮助简化它,如果它变得重复(如果你做了很多它可能会这样做)。

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

You could then call this with auto uptr = make_sdl_ptr(); 然后你可以用auto uptr = make_sdl_ptr();调用它auto uptr = make_sdl_ptr();

Angew's answer with a DefaultConstructible deleter calling your function is also a really nice solution. Angew用DefaultConstructible删除器调用你的函数的答案也是一个非常好的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM