Why does my unique_ptr think is has a null function pointer deleter? [duplicate]

好久不见. 提交于 2019-12-10 04:22:58

问题


I'm trying to learn SDL using C++. I've created a window.h header and a window.cpp source file for storing a Window class. In window.h it looks something like this:

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

with some of the code in the class omitted. Then, in my source file, in the definition of the default constructor, I do this:

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

However, when I go to compile, I'm told that unique_ptr [is] constructed with null function pointer deleter, which as far as I can tell is false. Maybe I'm misunderstanding how to use a unique_ptr's deleter, but I cannot figure out what's wrong. Is there something I'm missing or have I completely misunderstood what I'm doing?


回答1:


The problem is that in your constructor, you use assignment instead of initialization for the members window and renderer. Your members are implicitly default initialized, which generates an error.

But why is this so and how to change it?

If you're new to C++ this might sound a bit strange, but any class member is initialized before the constructor function body is evaluated. Per default, each member will be initialized with its default constructor, or left uninitialized (if it's a primitive type like int). If you want to change this behavior (i.e. if you want to initialize it with something different, like you want), you have to use the member initializer list.

Example:

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

Note: Since C++11, you can also initialize members at their definition directly (like you can do it in Java for example), but in your case this would make the header look too complex. Also, this wouldn't fit to the rule of encapsulation (in most cases, only the class implementation should know what to do with private members).




回答2:


Use a member initializer list:

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

By the time the body of a constructor runs, all members shall already be initialized (default constructed unless you explicitly do something else, like above). Thereafter, you can only assign to them.



来源:https://stackoverflow.com/questions/22915631/why-does-my-unique-ptr-think-is-has-a-null-function-pointer-deleter

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!