C++ 堆栈分配对象,显式析构函数调用

Posted

技术标签:

【中文标题】C++ 堆栈分配对象,显式析构函数调用【英文标题】:C++ stack allocated object, explicit destructor call 【发布时间】:2009-10-28 16:34:25 【问题描述】:

我在处理现有库时遇到了一个奇怪的析构函数用法。当可能需要再次使用该对象时,显式调用了堆栈分配的 stl 向量的析构函数。这些向量对象是 stl 向量类的稍微定制的版本,具有专门的clear 方法。在析构函数体中存在两个方法调用:clear()_Tidy()

我一直在想一个很好的理由,为什么要调用这个析构函数,而不仅仅是 clear,但我不知所措。任何人都解释了为什么这可能是一个好主意?

【问题讨论】:

你能提供一个代码示例,向量 dtor 以及它是如何调用的吗? 向我们展示向量是如何创建的。 向量是使用默认构造函数通过一个简单的声明创建的。 _Tidy() 据我所知释放内存。一个例子:CustomVector 向量; ...稍后的向量。~CustomVector(); "向量是使用默认构造函数创建的,通过一个简单的声明。"如果是这样(我想你的意思是 definition),那么显式调用它的 dtor 应该有很好的理由并且非常小心。 【参考方案1】:

clear() 不能保证实际释放向量中分配的存储空间; MSVC 实现中的 _Tidy() 实际上会释放该存储空间,因此这可能是作为优化完成的。

这是一件邪恶的事情,但你可以合法地这样做(没有未定义的行为),只要存储被完全占用所有存储的相同类型的对象(忽略 cv 限定符)重用:

T automatic;
automatic.T::~T();
new (&automatic) T();

C++ 标准的第 3.8.7 节描述了这种使用场景并解释了它的合法性;它甚至包括一个与上面类似的例子。

【讨论】:

【参考方案2】:

这个类可以使用某种placement new 方法吗?那是我唯一一次看到显式析构函数在使用中。

【讨论】:

在我写作的时候打败我。 ;)【参考方案3】:

大向量?

猜想...当clear() 被调用时,向量通常会被清空,但内存不会被释放。这就是为什么有模式

std::vector<T>().swap(vector_to_clear);

清空向量以供重用并清除分配的内存。

也许原作者不知道这种模式,并试图以这种邪恶的方式摆脱分配的内存。 (我认为_Tidy 释放了分配的内存)

【讨论】:

向量大小不一,但没有一个错误的大。我很想知道原作者对此的意图,希望这只是一个错误的内存释放 我的第一个问题是这种情况是:签入评论是什么?【参考方案4】:

这绝对不是一个好主意。析构函数开始运行后对对象的任何操作都会产生未定义的行为。

【讨论】:

或者更确切地说,在析构函数完成之后?我想如果您在对实例进行任何其他操作之前以及在它超出范围之前在同一位置使用放置新构造另一个实例,这可能是有效的。 这些操作包括在作用域结束时自动调用dtor。 @UncleBens:不,一旦析构函数启动,您应该认为您的对象不再存在...尝试使用基类的析构函数中的虚拟函数,该基类实际上使用堆分配的内存派生类...明白我的意思:)?【参考方案5】:

也许最初的编码人员关心对象在内存中的分配位置。

然后必须显式调用析构函数,按照this discussion。

【讨论】:

可能是这种情况,因为讨论的是堆栈分配的向量。

以上是关于C++ 堆栈分配对象,显式析构函数调用的主要内容,如果未能解决你的问题,请参考以下文章

具有显式析构函数和 std::unique_ptr<> 成员的类不能在 std::vector<> 中使用?

为啥在调用它的析构函数后我可以访问这个堆栈分配的对象? [复制]

在 C++ 中抛出后会调用析构函数吗?

C++ 类设计总结回顾------析构函数

堆栈上的对象被覆盖时不调用析构函数

C++:对象和类|| 类的构造函数与析构函数