将自定义删除器作为类成员的智能指针

问题描述 投票:0回答:1

我的情况如下:我有一个.dll文件和一个带有纯虚拟class MainWindow声明的.h标头。头文件中有两个类型定义:

typedef MainWindow* (*CREATE_INTERFACE)();
typedef void (*DELETE_INTERFACE)(MainWindow* Window);

允许我创建和删除与虚拟类相同类型的对象。

我希望在我的课程中定义对此动态库的加载支持,我们称其为class Loader。我希望我的一个类成员成为定义如下的智能指针:

std::unique_ptr <MainWindow,DELETE_INTERFACE> UI_Driver;

下面的简化代码(无错误处理):

class Loader
{
    private:
    HINSTANCE DllHandle;
    CREATE_INTERFACE FactoryFunction;
    DELETE_INTERFACE CustomDeleterFunction;
    std::unique_ptr<MainWindow,DELETE_INTERFACE> UI_Driver;

    std::unique_ptr<MainWindow,DELETE_INTERFACE> LoadExternalLibrary()
    {
        std::wstring WideFileName=L"MainWindow.dll";
        std::string FileName(std::begin(WideFileName),std::end(WideFileName));
        this->DllHandle=::LoadLibrary(WideFileName.c_str());
        // Get the function from the DLL
        FactoryFunction=reinterpret_cast<CREATE_INTERFACE>(::GetProcAddress(DllHandle,"Create"));
        CustomDeleterFunction=(DELETE_INTERFACE)GetProcAddress(DllHandle,"Delete");
        return std::unique_ptr<MainWindow,DELETE_INTERFACE>(FactoryFunction(),CustomDeleterFunction);
     };

     UI_Service() : UI_Driver(LoadExternalLibrary())
     {

     }

     ~UI_Service()
     {
         if(UI_Driver)
             ::FreeLibrary(this->DllHandle);
     }

     void ShowWindow()
     {
        UI_Driver->Show();
     }
};

该代码正确编译,从.dll库加载函数也成功。标头中定义的MainWindow具有绘制用户界面的Show()方法。如果尝试使用ShowWindow()中的class Loader方法像上面一样调用它,则不会出现该窗口。

int main()
{
 Loader MyLoader;
 MyLoader.ShowWindow(); // <- window does not appear, program crashes
}

但是如果在LoadExternalLibrary()方法中创建指针后立即调用此方法,则会显示如下:

所以改为:

return std::unique_ptr<Eol_MainWindow_Driver_Generic,DELETE_INTERFACE>(FactoryFunction(),CustomDeleterFunction);

我可以写:

std::unique_ptr<Eol_MainWindow_Driver_Generic,DELETE_INTERFACE> UI(FactoryFunction(),CustomDeleterFunction);
UI->Show(); // <- Window appears
return UI; // <- It will never happen because the Show() is blocking the thread

发生了什么事?为什么创建的带有自定义删除程序的unique_ptr在复制后会停止工作?

c++ c++11 dll smart-pointers
1个回答
0
投票

通过返回unique_ptr,您可能会销毁它。

// funky indent to fit in SO width
return std::unique_ptr<
    Eol_MainWindow_Driver_Generic,DELETE_INSTANCE
>(
    FactoryFunction(),CustomDeleterFunction
);

除非您使用兼容C ++ 17的编译器进行编译,否则您无法保证1在调用者站点进行复制后创建的临时unique_ptr不会被销毁。在这种情况下,您需要移动指针:

// funky indent to fit in SO width
return std::move(std::unique_ptr<
    Eol_MainWindow_Driver_Generic,DELETE_INSTANCE
>(
    FactoryFunction(),CustomDeleterFunction
));

[1)进一步说明:How does guaranteed copy elision work?

© www.soinside.com 2019 - 2024. All rights reserved.