编程中级C++开发者

在C++中,内置(原始)类型和用户定义类型是什么,它们有什么区别,以及在设计复杂程序时为什么这很重要?

用 Hintsage AI 助手通过面试

回答。

问题的历史:

C++是在C的基础上构建的,C提供了一小部分内置类型:数字、字符和数组。随着语言的发展,出现了结构、类和枚举等概念,它们便成为了用户定义类型。

问题:

程序中的数据类型决定了变量所占用的内存量、它如何被初始化、复制、销毁和比较。内置类型具有标准定义的行为,而用户定义类型则需要明确描述所有方面。管理用户定义类型的错误可能导致崩溃、内存泄漏、不公平的对象比较等。

解决方案:

内置类型包括int、float、double、char、bool等其他“原始”类型。用户定义类型是您创建的任何结构、类和联合。对于复杂的任务,需要引入具有关联的复制、比较和资源管理语义的用户定义类型。

代码示例:

// 内置类型 int x = 5; // 用户定义类型 struct Point { double x, y; }; Point a = {1.0, 2.0}; // 带有资源的类 class MyFile { public: MyFile(const std::string& fn) : f(fopen(fn.c_str(), "r")) {} ~MyFile() { if (f) fclose(f); } private: FILE* f; };

关键特点:

  • 内置类型:快速、复制简单、大小和行为已知。
  • 用户定义类型:用于描述复杂实体,可以管理资源,需要实现构造函数和析构函数。
  • 控制操作的语义(+、=、==)、转换及其他行为方面。

误导性问题。

用户定义类型是否可以完全像内置类型一样表现(例如,默认通过==进行比较)?

不可以,==的比较仅从C++20开始默认通过defaulted operator==工作,在此之前需要明确定义。

如果类只持有原始指针(int、FILE等),可以不实现复制构造函数和析构函数吗?**

不可以,在这种情况下,默认的复制将是“浅复制”,这将导致内存/资源泄漏或双重释放。需要实现“五法则”。

结构的默认值是否会被初始化为零(Point p;)?

不会,局部结构可能未被初始化,内存内容是随机的。请显式使用初始化。

常见错误和反模式

  • 忽视用户定义类型的显式初始化。
  • 不为动态内存的类实现析构函数和复制构造函数。
  • 尝试通过内置类型(例如,原始指针)管理资源。

生活中的例子

负面案例:

一个文件的包装类没有实现析构函数。当处理成千上万的文件而未关闭描述符时,程序一直在工作。

优点:代码更少,外观简化 缺点:资源泄漏,不稳定的行为

正面案例:

一个类实现了RAII——在构造函数中打开文件,在析构函数中关闭,禁止复制。

优点:可靠、安全、干净的接口 缺点:需要记住“五法则”,需要编写更多代码