C++中的基元类型有析构函数吗?
Do Primitive Types in C++ have destructors?
这个问题来自我试图理解智能指针的动机,在智能指针周围创建一个包装类,以便您可以添加自定义析构函数。指针(以及整数、布尔值、双精度值等(没有析构函数吗?
从技术上讲,非类类型(C++外行术语中通常称为"基元类型"的术语(没有析构函数。
C++ Standard 只在类的上下文中提到真正的析构函数,请参阅C++标准中的 [class.dtor]。除此之外,C++还允许使用相同的表示法在非类对象上调用析构函数,即以下代码是有效的:
void foo(int z) {
using T = int;
z.~T();
}
这被称为"伪析构函数",专门用于允许编写通用模板化代码以相同的方式处理类和非类类型。此调用根本不执行任何操作。此语法在 C++ 标准的 [expr.prim.id] 中定义。
基元类型(及其化合物(具有平凡的析构函数。这些不执行任何操作,并且具有特殊的措辞,在某些情况下可以完全跳过它们。
然而,这与C++为什么有智能指针是正交的。原始指针是非所有者的:它指向另一个对象,但不影响其生存期。另一方面,智能指针拥有(或共享(其尖头,将其生命周期与自己的生命周期联系起来。这是在他们的析构函数中实现的,以及其他特殊功能。
除了到目前为止给出的答案之外,自 C++20 以来,对非类对象的伪析构函数调用将始终结束其生存期。因此,在调用后访问对象的值将具有未定义的行为。但是,这并不意味着编译器必须为此类调用发出任何代码。它仍然有效地什么也没做。
不,指针没有析构函数。通过普通旧指针引用的对象必须delete
d 以避免内存泄漏,然后调用对象的析构函数,但编译器不会自动调用delete
,即使指针超出范围 - 如果程序的另一部分也有指向同一对象的指针怎么办?
智能指针不是关于调用自定义析构函数,而是关于确保在超出范围时自动清理内容。这种"清理"可能是删除拥有的对象,free
任何malloc
的内存,关闭文件,释放锁等。
析构函数用于释放对象可能已使用的资源。
对于指针,如果不从堆中分配新内存,则不需要删除。
C 和 C++有两种存储变量的方法:堆栈和堆。
堆栈用于静态内存,编译器会处理这个问题。堆用于动态内存,如果您使用它,则必须注意这一点。
执行基元类型声明时,将为变量分配堆栈内存。
使用new
声明对象时,此对象存储在堆中,您需要在使用完堆时将其删除,否则将出现内存泄漏。
基本上,如果你有新的东西,你只需要delete
。
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 不命名构造函数和析构函数上的类型错误
- C++中的基元类型有析构函数吗?
- LINUX 操作系统上的错误:令牌之前预期的构造函数、析构函数或类型转换'('?
- 显式调用 typedef'd 类类型的析构函数的正式正确方法
- 即使基类和派生类只使用基元数据类型,我是否需要定义虚拟析构函数
- 在从仅移动类型派生的类中定义析构函数在使用 std::vector emplace_back或push_back创建时会
- 当 T 具有非平凡析构函数时,类类型 T 的对象是否可以常量初始化?
- 非默认析构函数会导致不完整的类型错误
- 错误 c++ 在令牌之前'('预期的构造函数、析构函数或类型转换
- 触发的断点(析构函数)与类模板类型是自身的一个版本
- 错误:在“(”标记之前进行预期的构造函数、析构函数或类型转换.即使我有一个构造函数
- GCC 9.1 返回 void& 作为显式析构函数调用的结果类型。这是一个错误吗?
- 获取错误:在“(”标记之前进行预期的构造函数、析构函数或类型转换
- 不是多态类型,或者为什么我们在这里需要虚拟析构函数?
- 如何销毁通过"放置新"构造的无析构函数类型
- C++联合如何知道其中存储的类型以及要调用哪个析构函数
- 错误:令牌之前的预期构造函数、析构函数或类型转换'*'
- 不同的析构函数类型
- 需要构造函数/析构函数/类型转换错误