如何在不导出对象的情况下自动删除对象

How to delete object automatically without exporting them

本文关键字:对象 情况下 删除      更新时间:2023-10-16

我开发了一个为客户端提供各种api的库。我们有很多限制,其中之一就是我们应该尽可能地避免导出类。在某些平台上,当客户使用各种各样的编译器时,这是一个问题,这些编译器可能会以不同的方式命名。

由于这个原因,我们向客户提供接口(纯虚拟),这有效地隐藏了我们的实现。我们使用工厂方法将对象传递给客户端,例如IUtfString* createUtfString(),它通常与某些destroyUtf8String(IUtfString* string)函数配对。

在某些地方,我们有IUtfString* IUtfString::copy()调用,它也与destroy函数或IUtfString::release()函数配对。

这个工作,一切都很好,到目前为止,但它看起来如此1990 C。它完全避免了RAII,只是重用了c中的不透明指针。是否有某种习惯用法可以自动销毁那些工厂创建的对象,而不必导出大对象?pimpl习惯用法可能会有所帮助,因为它将隐藏UtfString对象的大部分,但它仍然迫使我们通过库/dll导出对象,这是我们希望避免的。

我们内部确实有boost支持,但我们也避免将这些类型暴露给客户端。

您可以尝试对shared_ptr<IUtfString>进行类型定义,然后更改createUtfString()函数以返回具有自定义删除器的实例。

之类的
typedef boost::shared_ptr<IUtfString> UtfString;
/*does nothing now. Designed for code compatibility*/ 
void destroyUtfString( IUtfString* ) {}
UtfString createUtfString( ... ) {
  return boost::shared_ptr<IUtfString>(oldCreateUtfString(),oldDestroyUtfString);
}

如果您能够向客户端代码公开实际的c++类,只需像往常一样使用析构函数和复制构造函数。您仍然可以使用特殊的工厂函数来创建实例和返回指针,但是客户端将在这些指针上调用delete,而不是调用特殊的销毁函数,因此客户端可以使用标准的智能指针类来避免资源泄漏。

但是,如果您试图避免c++名称混淆问题,则可能是您的库只公开structextern "C"函数,而不是类。这意味着你的库确实有一个C API,即使它是用c++内部实现的,而且你不能提供析构函数,因为你不能有extern "C"析构函数。如果是这种情况,只需认识到您提供的是C API,而不必担心它缺乏c++特性。

我也用过类似的技巧。基本思想是假设虚函数表比名称混淆更稳定。

然后导出函数为extern "C"

我要做的是创建仅标头包装器,将这些返回值包装在std::shared_ptrstd::unique_ptr中。并确保你不输出它们。它们调用extern "C"导出函数。(或boost,或roll-your-own)

由于它们在头文件中是inline,因此它们在"客户端一侧"编译。所以版本和变形并不重要!

这确实强制客户端在回调到你的API时使用.get():但是你可以使用更多的头包装器来处理这个问题,这些包装器接受智能指针和.get()(或.release())。

如果你有侵入式引用计数,那么你的shared_ptr的破坏者可以将侵入计数减少一个:这使得传入原始指针并返回shared_ptr s更实用。

相关文章: