NoS*_*tAl -1 c++ pimpl-idiom shared-ptr c++20
AFAIKunique_ptr
与 PIMPL 一起使用非常棘手,因为删除器是unique_ptr
类型的一部分,因此它不适用于不完整的类型。另一方面,shared_ptr
使用动态删除器,因此它可以处理不完整的类型。
shared_ptr
无论我是否需要,都存在给我原子操作的性能问题。
我可以使用其他更快的替代方案吗std::
?我显然对类型擦除很满意,我说的是原子引用计数的成本。
#include <any>
#include <memory>
#include <iosfwd>
std::shared_ptr<std::fstream> sp;
// unique_ptr requires complete type
// std::unique_ptr<std::fstream> up;
std::any a;
#include <fstream>
int main() {
// any requires copy_constructible
// a = std::fstream{};
sp = std::make_shared<std::fstream>();
}
Run Code Online (Sandbox Code Playgroud)
笔记:
any
,但它不适用于某些类型。unique_ptr
函数永远不会“告诉”删除器构造的对象是什么(为删除器提供一种学习如何销毁对象的方法)。PS 我知道很久以前boost::shared_ptr
就有宏来禁用原子引用计数,但即使仍然支持我也不想切换到boost::shared_ptr
.
首先,请注意,“原子引用计数”shared_ptr
只有在您实际使用时才会出现问题。由于您的类是不可复制的(这对于接口类型来说是有意义的,并且由于您愿意使用unique_ptr
,所以它必须是不可复制的),因此计数只会在构造和销毁时修改。所以...你不应该关心; 即使原子引用计数实际上在性能方面很重要,它也将是伴随它的内存分配/取消分配成本的舍入错误。
至于您的实际问题,您在这里收到编译错误的唯一原因是因为您强制编译器unique_ptr<T>
从仍然不完整的地方实例化 的析构函数T
。
在PIMPL 的实际使用中,您将拥有一个定义公共接口并声明私有实现的头文件,以及一个或多个提供这些实现的 .cpp 文件。unique_ptr<T>
只要公共接口类型的析构函数未在标头中定义,就可以在这些情况下工作:
///Interface.h
class Impl;
class Interface
{
private:
unique_ptr<Impl> impl_;
public:
~Interface(); //Declaration only; prevent compiler-definition in header
};
///Interface.cpp
class Impl {...};
Interface::~Interface() = default;
Run Code Online (Sandbox Code Playgroud)
这可以防止包括 header 在内的人员实例化 的unique_ptr<Impl>
析构函数。
归档时间: |
|
查看次数: |
285 次 |
最近记录: |