混淆使用 unique_ptr 和自定义删除器
Confused using unique_ptr and a custom deleter
我正在尝试将 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 的特性,这对我来说很难。
Is uptr_1 correctly declared and initialized to nullptr
是的,默认构造的 unique_ptr
将引用 null。
if so, how can I assign the pointer and the deleter function?
您应该使用参数
构造 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 删除器的回答也是一个非常好的解决方案。
您可以使用指针和删除器初始化 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);
要缩短 long 类型,确实可以使用类型别名(typedef
或 using
):
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());
我会选择 decltype
:
std::unique_ptr<SDL_Surface, decltype(&FreeSurface)> uptr_1(
CreateSurface(),
FreeSurface
);
我正在尝试将 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 的特性,这对我来说很难。
Is uptr_1 correctly declared and initialized to nullptr
是的,默认构造的 unique_ptr
将引用 null。
if so, how can I assign the pointer and the deleter function?
您应该使用参数
构造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 删除器的回答也是一个非常好的解决方案。
您可以使用指针和删除器初始化 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);
要缩短 long 类型,确实可以使用类型别名(typedef
或 using
):
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());
我会选择 decltype
:
std::unique_ptr<SDL_Surface, decltype(&FreeSurface)> uptr_1(
CreateSurface(),
FreeSurface
);