DLL exporting causing issues with unique pointers

走远了吗. 提交于 2021-02-05 06:25:05

问题


I've got two files:

Header.h

#pragma once

#ifdef UNIQUEPTRISSUE_EXPORTS
#define UNIQUEPTRISSUE_API __declspec(dllexport)   
#else  
#define UNIQUEPTRISSUE_API __declspec(dllimport)   
#endif 

UniquePtrIssue.cpp

#include "stdafx.h"

#include "Header.h"

#include <memory>
#include <vector>

class UNIQUEPTRISSUE_API ClassA {

};

class UNIQUEPTRISSUE_API ClassB {
private:
    std::vector<std::unique_ptr<ClassA>> x;
};

Compiling raises the following error:

1>d:\program files (x86)\microsoft visual studio\2017\enterprise\vc\tools\msvc\14.14.26428\include\xutility(2443): error C2280: 'std::unique_ptr> &std::unique_ptr<_Ty,std::default_delete<_Ty>>::operator =(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function 1> with 1> [ 1> _Ty=ClassA 1> ]

Similar issues seem to arise when the accessing the copy constructor of a unique_ptr but they don't seem to apply.

Removing the UNIQUEPTRISSUE_API/__declspec(dllexport) from both class declarations seems to make the error go away.

Obviously something is going on with the __declspec(dllexport) declaration that I don't understand. Is there any way I can use unique_ptrs between exported classes?


回答1:


When you declare a class with declspec(dllexport), the compiler must generate all of the member functions of the class, including the default constructors, copy assignment, etc functions since it doesn't know which ones may be needed by the importing module. This is described in Using dllimport and dllexport in C++ classes.

Since a unique_ptr cannot be copied, its copy constructor and copy assignment operators are deleted, and when the vector object tries to use them you get the C2280 error.

When you don't include declspec(dllexport), the compiler will only generate the functions that are actually used, and the problematic copies are avoided.

One way around this problem is to export the individual class member functions, which may mean specifying some of them as defaulted. virtual functions would not need to be exported, since they're handled by the vtable.

Another workaround is to explicitly delete the copy constructor and copy assignment operator. Since this will prevent the creation of a default constructor and move constructor/assignment functions, you may need to default those in.

class UNIQUEPTRISSUE_API ClassB {
public:
    ClassB(const ClassB &) = delete;
    ClassB &operator=(const ClassB &) = delete;
    // You may need to explicitly default these if they are used
    ClassB() = default;
    ClassB &operator=(ClassB &&) = default;
    ClassB(ClassB &&) = default;
private:
    std::vector<std::unique_ptr<ClassA>> x;
};



回答2:


You can expose class differently:

class ClassB {
private:
    std::vector<std::unique_ptr<ClassA>> x;

public:

    UNIQUEPTRISSUE_API ClassB(ClassB&&) {

    }

    UNIQUEPTRISSUE_API ClassB& operator==(ClassB&&) {

        return* this;

    }

private:

}

i.e: don't export the entire class, but the single function. I try this on vs2010 and vs2017



来源:https://stackoverflow.com/questions/51033325/dll-exporting-causing-issues-with-unique-pointers

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