在导出的类中使用std::unique_ptr
Using std::unique_ptr in an exported class
我在DLL中有一个类,看起来像这样:
#ifdef LIB_EXPORT
#define LIB_API __declspec(dllexport)
#else
#define LIB_API __declspec(dllimport)
#endif
...
class LIB_API MyClass {
public:
// ...public interface...
private:
// ...some private fields...
std::unique_ptr<OtherClass> otherPtr_;
};
现在,我认为这可能是一个问题:如果客户端代码使用稍微不同版本的unique_ptr,那么MyClass对象的内存布局实际上会与DLL中的代码所期望的有所不同。
我真的不想使用Pimpl习惯用法来从公共头中隐藏unique_ptr
。我可能会推出自己的简化版unique_ptr
(我只需要它功能的一个子集,例如,我不需要自定义删除程序)。但是,在我尝试之前,有其他方法可以解决这个问题吗?
您推测的问题是非常真实的,它不仅适用于标准库类的布局,也适用于您自己的类。除非您的类符合标准布局规则,否则即使给定完全相同的源代码,不同的编译器也不应该使用相同的内存布局。答案是根本不应该导出C++类。
案例#1:如果您想要unique_ptr
来管理DLL的公共对象的生存期:
从DLL导出一个工厂函数和删除函数,并在公共头中放入一个包装类。包装器完全存在于客户端中,因此仅使用客户端版本的unique_ptr
。
包装类上未使用__declspec(dllexport)
。
案例#2:如果DLL内部使用unique_ptr
:
你应该使用继承而不是皮条客。公共头文件包含一个基类,该基类具有受保护的构造函数、纯虚拟成员函数,并且根本没有数据成员。同样,不使用__declspec(dllexport)
。dllexport
工厂函数用于创建新实例。在DLL中,您从该接口类型继承,派生类将添加所有数据成员和函数体。客户端永远看不到任何数据成员,因此您可以自由使用C++对象,并且使用的布局是DLL的本地布局。
这两者的副作用是,琐碎的成员函数不会内联,这可能会对性能产生负面影响。但是,为每个成员访问调用DLL是实现解耦的唯一方法。
- 使用std::multimap迭代器创建std::list
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- 来自 std::list 的迭代器 .end() 按预期返回"0xcdcdcdcdcdcdcdcd"但 .begin()
- 为什么 std::unique 不调用 std::sort?
- 我对 std::unique(算法)C++有问题
- std::shared_ptr::unique(),复制和线程安全
- 如何在C++03中用自定义谓词调用std::unique
- C++ std::unique并没有显示我对它的期望
- C++14 unique_ptr并使用已删除的函数'std::unique-ptr' unique_ptr错误
- 为什么 [std::unique] 不能应用于 [std::multiset]?
- 使用 std::unique 和 vector.erase 删除除最后一次出现的重复元素之外的所有元素
- 是否可以在 std::unique<T[ ]> 上应用 std::sort?
- std::unique 是否有大小限制
- 从 std::unique 返回的迭代器的用法
- 使 std::unique<T> 与 std::unique<const T, CustomDeleterType 兼容>
- Std::list.unique()应该使迭代器无效
- 无法使用初始化器列表构造 vector<std::unique<...>>
- 从自定义对象- std:unique的向量中消除重复项会导致崩溃
- 我能保证std::unique将保留第一个元素吗?
- 在 std::vector<std::unordered_set上使用 std::unique(<T>>