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

7
在处理现有库时,我遇到了一种奇怪的析构函数用法。当该对象可能需要再次使用时,显式调用了堆栈分配的stl向量的析构函数。这些向量对象是stl向量类的稍微定制版本,具有专门的clear方法。在析构函数体中存在两个方法调用:clear()_Tidy()
我一直在努力想到一个好的理由,为什么会调用这个析构函数而不仅仅是clear,但我束手无策。有人能解释一下为什么这样做是个好主意吗?

你能提供一份代码示例,展示向量 dtor 的使用方法吗? - Binary Worrier
展示一下向量是如何创建的。 - sbi
该向量是通过简单声明使用默认构造函数创建的。据我所知,_Tidy()会释放内存。一个例子: CustomVector<Value> vector;...稍后 vector.~CustomVector(); - Colin
向量是使用默认构造函数通过简单声明创建的。如果需要,可以显式调用其析构函数,但必须有非常充分的理由,并且需要非常小心谨慎地进行。 - sbi
5个回答

10

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

这是一件邪恶的事情,但只要存储空间被同一类型(忽略cv限定符)的对象重用,并且占用了恰好所有的存储空间,则可以合法地这样做(没有未定义的行为):

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

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


6

这个类是否需要使用某种放置new方法?那是我经常看到显式析构函数被使用的唯一时候。


我正在写作时被你抢先了。 ;) - John

6

大向量?

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

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

清空向量以便重复使用并清除分配的内存。

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


向量的大小不同,但没有错误地变得过大。我很想知道原作者的意图,希望这只是一个错误的内存释放问题。 - Colin
我的第一个问题是在这种情况下是:检入注释是什么? - sbi

2

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


或者说,在析构函数完成之后?我想,如果您在实例化对象之后立即使用放置 new 在同一位置构造另一个实例,并在实例超出作用域之前执行任何其他操作,那么这可能是有效的。 - UncleBens
这些操作包括在作用域结束时自动调用dtor。 - sbi
@UncleBens:不,一旦析构函数开始,您应该认为对象已经不存在了...尝试在基类的析构函数中使用虚函数,实际上使用派生类的堆分配内存...明白我的意思吗 :) ? - Matthieu M.

2
也许原始编码者关心对象在内存中的分配位置。
然后,必须显式调用析构函数,如此讨论所述。

这很可能是因为讨论的是一个堆栈分配的向量。 - Matthieu M.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接