Release() 和析构函数之间的区别?
Difference between Release() and destructor?
当我学习使用抽象接口将代码封装在动态库中时,似乎建议使用"Release(("函数来释放资源。现在我想知道为什么他们不只使用析构函数来发布?使用析构函数释放资源是否有任何问题,或者他们只是想使用智能指针?
这是推荐的代码:
// Interface like that ..
struct IXyz
{
virtual int Foo(int n) = 0;
virtual void Release() = 0;
};
// Xyz class definition, derived from IXyz
// ...
// Using in client ..
IXyz* pXyz = GetXyz(); //Use Factory function to create an object
if(pXyz)
{
pXyz->Foo(42);
pXyz->Release();
pXyz = nullptr;
}
现在我想改为编写以下代码:
// Interface
struct IXyz
{
virtual int Foo(int n) = 0;
virtual ~IXyz() {}; // I have moved Release()'s content into Xyz's destructor
};
// Client
IXyz* pXyz = GetXyz(); //Use Factory function to create an object
if(pXyz)
{
pXyz->Foo(42);
pXyz->~IXyz();
pXyz = nullptr;
}
这些代码都可以正常工作。所以我想知道这两种释放资源的方式之间的区别。我可以同时使用它们吗?多谢!
这只在Windows上是一个问题。通过 new 分配内存时,Win32可以使用DLL 或 EXE 的本地分配堆。这可能会导致在发布生成 DLL 中分配,但稍后在调试生成 EXE 中释放的问题。然后,调试堆将抛出一个错误,指出内存分配未知。
因此,要解决此问题,一般方法是确保为 DLL 堆中的 DLL 对象分配内存,并在同一堆中释放内存。
首先,让我们尝试上面描述的工厂方法。提供 DLL 导出的工厂方法来分配内存,例如
struct IXyz
{
EXPORT static IXyz* create();
};
// in cpp file
EXPORT IXyz* IXyz::create()
{
return new IXyz;
}
但是,现在这意味着您必须在同一位置释放内存,您可以通过以下两种方式之一执行此操作。选项一,提供 DLL 导出的发布方法。
struct IXyz
{
EXPORT static IXyz* create();
EXPORT void release();
};
// in cpp file
EXPORT void IXyz::release()
{
delete this;
}
另一种方法是使 dtor 虚拟化。它将确保在同一位置释放分配,但会通过 vtable 指针使结构大小膨胀。
如果您不想这样做,另一种方法是从基本 DLL(简单地调用全局 new/delete(导出一对自定义 malloc/free 函数。然后在从 DSO 导出的每个类中重载 new/delete。使用new/delete将不再给您带来问题。
除非你实际上大量使用DLL,并且你需要混合调试/发布版本,否则以上所有内容都是完全没有意义的。这些模式有其位置,但它们通常不是很好的模式。
首先,调用析构函数会破坏对象,但不会释放它的内存。事实上,很少需要完全调用析构函数,因为delete
(对于动态分配的对象(或超出范围(对于在堆栈/全局范围内分配的对象(已经调用析构函数并照顾内存。
现在,Release()
实际上做了一些非常不同的事情:它是(至少在我所知道的所有库中(称为引用计数的一部分。这是一种控制何时应delete
对象 -ed 的方法,具体取决于使用它的内容数量。因此,虽然调用析构函数(显式或通过调用delete
(肯定会销毁对象,但调用Release()
只是告诉库您不再使用该对象,并且库可以随时自由删除它 - 现在可能不是,因为库可能仍在内部使用该对象。
- C++中std::resize(n)和std::shrink_to_fit之间的区别
- int(c) 和 c-'0' 之间的区别。C++
- C++ 使用 assign 函数的字符串与直接使用 '=' 更改值的字符串之间的区别
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 我是C++编程的新手,这些代码之间有什么区别,我应该使用哪一个
- 在 const 函数中通过引用和指针返回之间的区别
- 我想知道长双倍和双倍之间的区别
- 这 4 个 lambda 表达式之间有什么区别?
- 结构体 S { int align; } 之间的区别;(struct 关键字后的名称)和 struct { int al
- (double) 和 double() 之间的区别
- & 和 * 之间的区别
- std::is_convertible 和 std::convertible_to 之间的区别(在实践中)?
- 析构函数和'delete'之间的区别
- 在 typedef 内部使用 const 关键字和在 typedef 外部使用 const 关键字之间有区别吗?
- 从预序遍历构造 bst 的 c++ 和 python 解决方案之间的区别
- vector.back() 和 vector[vector.size() - 1] 之间的区别?
- 空指针常量 (nullptr)、空指针值和空成员指针值之间有什么区别?
- 函数签名与调用的函数不匹配,常量字符[]和字符*之间的区别?
- OpenMP #pragma omp for v/s #pragma omp parallel for 之间的区别?
- S() 与 S{} 之间的区别?