无法为unique_ptr返回类型返回nullptr

时间:2019-05-09 17:36:51

标签: c++ c++11 unique-ptr nullptr

我正在为SDL_Texture*原始指针编写一个包装,该包装返回一个unique_ptr

using TexturePtr = std::unique_ptr<SDL_Texture, decltype(&SDL_DestroyTexture)>;

TexturePtr loadTexture(SDL_Renderer* renderer, const std::string &path) {
    ImagePtr surface =
        loadImage(path);
    if (surface) {
        return TexturePtr(
            SDL_CreateTextureFromSurface(renderer, surface.get())
            , SDL_DestroyTexture);
    }
    return nullptr;
}

但是它给出了以下错误:

no suitable constructor exists to convert from "std::nullptr_t" to "std::unique_ptr<SDL_Texture, void (__cdecl *)(SDL_Texture *texture)>"

根据我的理解,可以通过传递nullptr来代替unique_ptr。我事件尝试在最后一次返回时传递空的unique_ptr:

return TexturePtr();

但是在构建过程中会遇到类似的错误。

请让我知道我在这里做错了。

Env: 编译器:Visual C ++ 14.1

2 个答案:

答案 0 :(得分:8)

unique_ptr(nullptr_t)构造函数要求删除程序是默认可构造的,并且它不是指针类型。您的删除程序不满足第二个条件,因为删除程序是函数的指针。参见[unique.ptr.single.ctor]/1[unique.ptr.single.ctor]/4

此限制是一件好事,因为默认构造删除器会导致nullptr和不确定的行为,当您尝试调用删除器时可能会导致段错误。

您可以将return语句更改为

return TexturePtr{nullptr, SDL_DestroyTexture};  // or just {nullptr, SDL_DestroyTexture}

或者,提供满足上述要求的删除器。我写了here的另一个答案中显示了这样一个选项。

答案 1 :(得分:-5)

编辑:实际上,我下面的示例过于简化,Pratorian关于删除器的提示可能是您遇到问题的线索。

您的期望是正确的,并且确实可以在GCC / Clang以及msvc的较新版本上使用-有关编译器输出,请参见https://godbolt.org/z/CU4tn6

#include <memory>

std::unique_ptr<int> f() {
    return nullptr;
}

您可以尝试不同的变体,例如

#include <memory>

std::unique_ptr<int> f() {
    return {};
}

但是否则我想您别无选择,只能升级编译器。