如果我删除一个对象,导致其析构函数被调用,内存是在析构函数完成执行之前还是之后被释放的?
只有最不派生的类子对象被销毁后,内存才会被释放。因此,如果您有:
class Base {
};
class Derived : public Base {
public:
~Derived();
};
首先销毁Derived
,然后销毁Base
,最后才释放内存。
将delete
分解为实际执行的步骤,就能比较清楚地看到何时删除了内存。因此,这样一个语句:
delete some_ptr;
大致相当于这个伪代码:
some_ptr->~some_ptr();
free( some_ptr );
delete
操作符确定,而是由类的定义确定。通常,它会进行本地清理并确保也调用其基类析构函数。delete
操作符释放了内存。
free
函数实际上是已删除类或全局类别的operator delete()
函数之一。这实际上释放了内存。free()
,那是 operator delete()
。 - sharptoothoperator delete()
- 全局或类特定的 - 用于在delete
语句上释放内存。 - sharptoothdelete
语句和operator delete()
函数。我想你是对的——像deallocateMemory()
这样的伪代码会更好。 - sharptooth析构函数执行完后,会调用operator delete释放内存,但具体什么时候释放内存取决于所使用的分配器。
我认为内存是在析构函数执行完毕后释放的。我知道当捕获异常时,对象的析构函数直到对象本身超出作用域才会被调用。
在C++中,析构是使用对象中可用的数据执行某些代码。这段代码是任意的。
释放内存是一种低级处理,通常由delete
运算符隐藏,不应在调用析构函数之前调用。
这最好由分配器接口总结:
allocate
和deallocate
用于操作原始内存construct
和destroy
用于调用对象的构造函数和析构函数它明确指出,construct
、destroy
和deallocate
只能在先前由该分配器分配的内存上执行。它还明确指出,destroy
不会释放内存,需要随后调用deallocate
。
请注意,这是一个低级接口,允许销毁一个对象并重用释放的空间来就地构造另一个对象。
class test { string a; ~test() {} };
在这个例子中,~test
析构函数是完全定义好的,类中没有直接管理的资源,因此什么也不做。系统将在~test
执行完成后,在a
子对象上调用~string
,而不是~test
。继承也是一样的,基类的析构函数会自动调用。 - David Rodríguez - dribeasbase
的析构函数。回到责任问题,如果成员持有需要特定管理且不由该类型的析构函数持有的资源--比如需要delete的指针并且没有析构函数--那么该资源必须在包含类中进行管理。 - David Rodríguez - dribeas~Derived()
里面显式调用this->~Base()
。然而,至少从正式定义的方式来看,~Derived()
应该负责调用this->~Base()
(以及你评论示例中的a.~string()
)。当使用delete
时,一个析构函数被调用,并且该析构函数负责调用所有清理工作,包括调用任何基类或成员析构函数(如果需要的话)。 - James McNellis