繁体   English   中英

Pimpl 没有通过转换指针的开销?

[英]Pimpl without the overhead by casting pointers?

使用 PIMPL 习语时,如果动态分配了 pimpled object,我们将遭受双指针重定向,例如,

auto obj = std::make_unique<PimplClass>();
obj->foo();  // Requires dereferencing {obj} and {obj.pimpl}

似乎如果我们强制我们的 class 的客户端通过std::unique_ptr构造实例,那么我们可以通过将实例指针重铸为某些实现定义的类型来“免费”(即,无需额外的取消引用)拥有 PIMPL 习惯用法在适当的时候:

// Header
struct SelfPimplClass final
{ // No member variables/implementation details.
  // ABI stable with respect to changes to the implementation.
  void foo();
  ~SelfPimplClass();
  static std::unique_ptr<SelfPimplClass> create();
};

// Implementation
struct SelfPimplClassImpl final
{
  int foo,bar,etc;
  void fooImpl() { printf("fooImpl()\n"); };
  ~SelfPimplClassImpl() { printf("~SelfPimplClassImpl()\n"); }
};

std::unique_ptr<SelfPimplClass> SelfPimplClass::create()
{
  auto *ptr = new SelfPimplClassImpl();
  return std::unique_ptr<SelfPimplClass>(reinterpret_cast<SelfPimplClass *>(ptr));
}

void SelfPimplClass::foo()
{
  return reinterpret_cast<SelfPimplClassImpl *>(this)->fooImpl();
}

SelfPimplClass::~SelfPimplClass()
{
  reinterpret_cast<SelfPimplClassImpl *>(this)->~SelfPimplClassImpl();
}

在客户端使用堆栈分配变量的应用程序中,与 PIMPL 相比没有优势,但在客户端无论如何都使用动态分配的情况下(例如,因为他们需要std::shared_ptr ),或者在 PIMPL 的情况下实例是从指针访问的,那么上面的代码似乎提供了显着的性能优势(memory 取消引用数量的一半),主要缺点是额外的样板代码(可以通过适当的模板抽象掉)和少量进行强制转换时未定义的行为。

这种方法直接等同于 C 中的常见做法,即使用 void 指针作为不透明类型,该类型在 function 实现中被强制转换为结构。 主要区别在于,我们没有声明面向公众的不透明类型void ,而是将其声明为空结构,以便我们可以提供成员函数。

鉴于 C 程序员几代人一直在使用 void 指针方法来实现与 PIMPL 相同的效果,但只有一个指针重定向,我总是发现令人惊讶的是,在 C++ 中,我们接受了两个重定向。 我是否遗漏了什么,如果没有,这种做法是否有名字,是否在野外使用? 另外,有没有办法避免reinterpret_cast的未定义行为?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM