C++中的基本数据类型有析构函数吗?

5
这个问题源于我想了解智能指针的动机,智能指针是围绕指针构造一个包装类,以便添加自定义析构函数。指针(还有整型、布尔型、双精度浮点型等)没有析构函数吗?

2
C++是一种多范式语言,这意味着不是所有的东西都必须是一个类。 - dandan78
@dandan78 你的意思是原始类型不是类,因此没有析构函数吗? - Joshua Segal
@JoshuaSegal 原始类型不是类。 - Jesper Juhl
@JesperJuhl 原始类型不存在(就像勺子一样)。相反,C++有非类类型,它们不是类,因为它们不是类类型。 - SergeyA
5个回答

17

从技术角度来说,非类类型(在普通语言中通常称为“原始类型”)没有析构函数。

C++标准仅在类的上下文中讨论真正的析构函数,请参见C++标准中的[class.dtor]。除此之外,C++还允许使用相同的表示法在非类对象上调用析构函数,即以下代码是有效的:

void foo(int z) {
    using T = int;
    z.~T();
}

这被称为“伪析构函数”,其存在仅是为了允许编写通用模板代码,以相同的方式处理类和非类类型。该调用完全不起作用。此语法在C++标准中的[expr.prim.id]中定义。


5

基本类型(及其复合类型)具有平凡析构函数。这些函数不做任何事情,并且具有特殊措辞,使它们在某些情况下可以完全跳过。

然而,这与C++为什么有智能指针是无关的。原始指针是非所有权的:它指向另一个对象,但不影响其生命周期。另一方面,智能指针拥有(或共享所有权),将其所指对象的生命周期绑定到自己的生命周期中。这就是在内部实现的,除其他特殊函数外,还有它们的析构函数。


那么,微不足道的析构函数到底是做什么的?它真的什么都不做吗? - Joshua Segal
3
@Joshua 是的,就是这样。它主要用于保持一致性,但被指定为无操作。 - Quentin
很有趣!将其与dandan78的评论联系起来,您会说原始类型是类还是另一种范例,就像dandan78所说的那样?如果它是不同的范例,那么我就不明白为什么c++要费心制作一个虚假的析构函数了。 - Joshua Segal
3
这与析构函数的相关性是错误的。请参考我的答案以获得正确解释。 - SergeyA

1

除了迄今为止在这里给出的答案,自从C++20以来,在非类对象上进行的伪析构函数调用将始终结束其生命周期。因此,在调用后访问对象的值将具有未定义的行为。然而,这并不意味着编译器必须为这样的调用发出任何代码。它仍然有效地什么也不做。


你能更详细地解释一下如何结束它的生命周期吗? - thedemons
1
@thedemons 在C++中,对象有其生命周期。除了少数例外情况,它们只能在其生命周期内使用。生命周期始于获取对象的存储空间并完成初始化(如果有的话)。类类型对象的生命周期通常在其析构函数被调用时结束,而非类类型的生命周期则以伪析构函数调用或在其存储期限结束时结束(例如,当自动存储期限变量的作用域结束时)。 - user17732522
1
@thedemons 请参考 https://www.eel.is/c++draft/basic.life#1 及其后续内容了解有关生命周期的详细信息,以及 https://www.eel.is/c++draft/expr#call-5.sentence-2 了解伪析构函数调用的影响。 - user17732522

0
不,指针没有析构函数。通过普通指针引用的对象必须被删除以避免内存泄漏,然后调用对象的析构函数,但即使指针超出范围,编译器也不会自动调用delete - 如果程序的另一部分也有对同一对象的指针呢?
智能指针并不是为了调用自定义析构函数,而是确保当它们超出范围时,事情会自动清理。这种“清理”可能是删除所拥有的对象,释放任何malloc的内存,关闭文件,释放锁定等。

-1

析构函数用于释放一个对象所使用的资源。

对于指针,如果你没有从堆上分配新内存,则不需要使用delete。

C和C++有两种变量存储方式:栈和堆。

栈是静态内存,编译器会自动处理。堆是动态内存,如果使用堆,则必须自己处理。

当进行基本类型声明时,变量的栈内存将被分配。

当使用new声明对象时,该对象存储在堆上,使用完毕后必须将其删除,否则就会出现内存泄漏。

基本上,只有在使用new时才需要使用delete


1
C++ 不称之为堆栈或堆,然而就语言而言,这些只是实现细节。 - drescherjm
@drescherjm 在涉及静态和动态内存时,C和C++使用相同的术语。 - MT756
1
如果你不从堆上分配新的内存,那么你就不需要析构函数。然而,析构函数不仅仅用于释放内存。一个类在其析构函数中可能会做很多事情,这些事情可能与对象是使用自动存储还是自由存储无关,但仍然有意义。 - Jesper Juhl
@JesperJuhl 已收到。已编辑。 - MT756
这与非类类型的销毁有什么关系? - interesting

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