C++中是否有指针的析构函数?

5
string * str=new string;
delete str;

当我删除指向对象的“str”时,是否会调用两个析构函数-一个用于指针本身,另一个用于它所指向的对象?

指针的析构函数会执行什么操作?


3
我不理解这个问题。请尽可能用正确而完整的英语句子进行写作,即使这对我来说也不是母语-现在这个问题根本没有意义。 - Niels Keurentjes
3
我猜想英语不是你的母语,但我担心你的问题实际上不够清晰明确。我将编辑你的问题以澄清我认为你的意思(否则我认为你的问题会很快被关闭),但如果不符合你的意图,请随时回滚或更改。 - Vicky
6个回答

16

delete的作用是销毁给定指针所指向的对象(在本例中就是string对象)。指针本身由str表示,具有自动存储期,当其像任何其他局部变量一样超出其作用域时将被销毁。

然而,请注意,非类类型没有析构函数。因此,即使您对非类类型使用delete,也不会调用析构函数,但是当指针超出其作用域时,它将像任何其他自动变量一样被销毁(这意味着指针仅到达其生命周期的末尾,尽管指针指向的内存未被释放,直到您使用delete显式释放它)。


1
非类类型的“析构函数”通常通过移动堆栈指针实现。这也是类类型对象在其析构函数中发生非平凡操作后自动存储时所发生的情况。 - rubenvb
2
@rubenvb 移动堆栈指针与销毁无关。局部变量的存储通常是通过改变堆栈指针来分配和释放的。这通常在函数的开始和结束时完成,而不是在标准实际要求时(根据“好像”规则)。 - James Kanze
@James,我并不是想说那样的话。我的意思是你所说的。但我相当确定类类型的原始内存(de)分配也是通过移动堆栈指针来完成的。在原始分配和释放之间,构造函数和析构函数的非平凡代码被执行。 - rubenvb
@rubenvb:让我们不要通过重新定义它来混淆“析构函数”的术语。在C++中,“析构函数”这个术语已经有了明确定义的含义,特别是当我们谈论“类型”时。 - Nawaz
@rubenvb 内存分配的方式取决于对象的生命周期,与类型以及是否有析构函数无关。 - James Kanze

4
指针本身并没有被 delete 语句销毁。但是,像任何作用域变量一样,它在作用域结束时被销毁。
示例:
void Function()
{
    string * str=new string;
    delete str; // <-- here the string is destructed
} // <-- here the pointer is "destructed", which is mean it's memory freed from the stuck but no actual destruction function is called..

4
析构函数的概念仅适用于对象(即使用classstruct定义的实体),而不适用于普通类型,例如指针。指针的生存方式与int变量相同。

在C++中,“对象”(严格意义上的)是内存区域。我想你指的是类类型。 - rubenvb

1
当我删除指向对象的“str”时,是否会调用两个析构函数-一个用于指针本身,另一个用于它所指向的对象?
不会。delete接受一个指针参数。它销毁被指向的对象(如果有析构函数,则使用其析构函数,否则不执行任何操作),并释放被指向的内存。您必须先使用new来分配内存并在其中创建对象。
指针本身不受影响;但是它不再指向有效的对象,因此不能对其进行任何操作。这有时被称为“悬挂指针”。
指针的析构函数会做什么?
什么也不做。只有类类型有析构函数。

1

像你所举的std::string*的裸指针一样,其析构函数是平凡的(就像其他原始类型:intdouble等的析构函数一样)。

智能指针类具有非平凡的析构函数,可以执行释放资源、调整引用计数等操作。


0

我喜欢从每种类型都有一个析构函数的概念中获得的简化。这样,即使存储值的类型是 int 或指针,模板明确销毁存储的值时也不会出现精神上的故障:

template <class T> struct wrapper {
    unsigned char data[sizeof(T)];
    wrapper(T t) { ptr = new (data) T; }
    ~wrapper() { (T*)&data->~T(); } // ignore possible alignment problem

wrapper<int> i(3);

然而,对于int和指针的析构函数是非常微不足道的:它们什么也不做,也没有任何地方可以查看析构函数的定义,因为这个定义不存在。因此,合理地说它们没有析构函数。

无论哪种方式,当指针超出作用域时,它只是消失了;没有特殊的代码运行。


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