为什么我的unique_ptr认为有一个空函数指针删除器?

时间:2014-04-07 14:41:12

标签: c++ sdl unique-ptr

我正在尝试使用C ++学习SDL。我创建了一个window.h标头和一个window.cpp源文件,用于存储Window类。在window.h中,它看起来像这样:

Class Window {
public:
  Window();
    . . .
private:
  std::unique_ptr<SDL_Window, void (*)(SDL_Window*)> window;
  std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)> renderer;
    . . .
}

省略了类中的一些代码。然后,在我的源文件中,在默认构造函数的定义中,我这样做:

Window::Window() {
  window = std::unique_ptr<SDL_Window, void (*)(SDL_Window*)>(nullptr, SDL_DestroyWindow);
  renderer = std::unique_ptr<SDL_Renderer, void (*)(SDL_Renderer*)>(nullptr, SDL_DestroyRenderer);
}

然而,当我去编译时,我被告知unique_ptr [is] constructed with null function pointer deleter,据我所知,这是假的。也许我误解了如何使用unique_ptr的删除器,但我无法弄清楚出了什么问题。有什么我想念的东西,或者我完全误解了我在做什么?

2 个答案:

答案 0 :(得分:5)

问题在于,在构造函数中,您对成员windowrenderer使用分配而不是初始化。您的成员默认默认初始化,这会产生错误。

但为什么会如此以及如何改变呢?

如果您是C ++的新手,这可能听起来有点奇怪,但在评估构造函数体之前,任何类成员都已初始化。默认情况下,每个成员将使用其默认构造函数进行初始化,或者保持未初始化(如果它是int之类的基本类型)。如果你想改变这种行为(即如果你想用不同的东西初始化它,就像你想要的那样),你必须使用member initializer list

示例:

Window::Window() :   // <-- put a colon here
    windows(nullptr, SDL_DestroyWindow),     // here comes the member init list
    rendered(nullptr, SDL_DestroyRenderer)
{
}

注意:从C ++ 11开始,您也可以initialize members at their definition directly(就像您可以在Java中一样),但在您的情况下,这会使标题看起来过于复杂。此外,这不适合封装规则(在大多数情况下,只有类实现应该知道如何处理私有成员)。

答案 1 :(得分:1)

使用成员初始化列表:

Window::Window()
    : windows(nullptr, SDL_DestroyWindow), rendered(nullptr, SDL_DestroyRenderer)
{
    // empty
}

当构造函数的主体运行时,所有成员都应该已经初始化(默认构造除非你明确地做其他事情,如上所述)。此后,您只能分配给他们。