【问题标题】:Shared pointer only initialising via std::shared_ptr. The std::make_shared constructor is not working共享指针仅通过 std::shared_ptr 初始化。 std::make_shared 构造函数不起作用
【发布时间】:2016-08-12 14:19:47
【问题描述】:

我正在使用 SDL2 和 C++ 制作一个基本游戏。我一直在慢慢将我对原始指针的不良使用改变为更安全的智能指针。

_window 变量是一个私有类成员:

private:
    std::shared_ptr<SDL_Window> _window;

以下代码有效:

_window = std::shared_ptr<SDL_Window>(SDL_CreateWindow(
        "Game",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        SCREEN_WIDTH,
        SCREEN_HEIGHT,
        SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
));

以下代码不起作用:

_window = std::make_shared<SDL_Window>(SDL_CreateWindow(
        "Game",
        SDL_WINDOWPOS_UNDEFINED,
        SDL_WINDOWPOS_UNDEFINED,
        SCREEN_WIDTH,
        SCREEN_HEIGHT,
        SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE
));

抛出以下错误:

C:\...\include\type_traits(984): error C2027: use of undefined type 'SDL_Window'

这很令人困惑,因为type_traits 是标准库的一部分。因此,我不确定错误的根源在哪里,但是在这里包含我的整个项目是不可行的。

仅将std::shared_ptr 更改为std::make_shared 会导致抛出此类错误的原因是什么?

【问题讨论】:

  • 两者都不起作用,因为您必须提供自定义删除器。
  • 我有什么特别的方法吗?
  • @Ashley: "这很令人困惑,因为 type_traits 是标准库的一部分。" 仅仅因为错误的位置在标准库中确实如此not 表示它是该错误的来源。就像你给一个函数传递一个 NULL 指针一样,即使是你的代码做错了,也会在那个函数中访问 NULL 指针。

标签: c++ c++11 pointers sdl smart-pointers


【解决方案1】:

首先要解决您的问题:make_shared 仅在使用 new 获取资源的情况下才有帮助,在这种情况下它不是。您必须使用普通的shared_pointer 构造函数和SDL_CreateWindow 返回的资源。但这还不是全部,您还必须传入一个知道如何调用 SDL_DestroyWindow 来释放资源的删除器。

【讨论】:

    【解决方案2】:

    make_shared 用于创建一个新对象,而不是用于假设现有对象的所有权。
    该函数自己构造对象,因此它需要类定义。

    ("Make shared" 不是"make this pointer shared",而是"make an object that can be shared"。这是"make me a pizza"的"make",而不是"make me a rockstar"的"make" " - 即创造,而不是转变。)

    您不能在此处使用make_shared,因为创建SDL_Window 的唯一方法是通过SDL_CreateWindow
    (因为窗口已经存在,所以没有意义。)

    您还需要将自定义删除函数传递给构造函数,因为 SDL 需要特定函数来销毁窗口:

    _window = std::shared_ptr<SDL_Window>(SDL_CreateWindow("Game", ...), SDL_DestroyWindow);
    

    【讨论】:

    • 非常感谢大家到目前为止的回答。现在这一切都很清楚了。还为包含该语法和有关传递解构函数的附加信息而欢呼。
    • 这为“给我做披萨”带来了全新的意义。
    【解决方案3】:

    std::make_shared&lt;T&gt; 旨在实际构造 T 类型的对象。 SDL_Window 是一个不完整的类型,不能在 SDL 本身之外构建。该类型的对象只能通过像 SDL_CreateWindow 这样的 SDL 调用来构造。

    只有在 make_shared 自身内部构造对象时,才应该使用 make_shared。而你不是。所以直接使用shared_ptr&lt;T&gt;即可。

    【讨论】:

      猜你喜欢
      • 2020-01-27
      • 2015-08-05
      • 2015-08-28
      • 2013-08-20
      • 2018-01-13
      • 2015-10-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多