C ++ 需要注意的问题 FAQ
### C++ 需要注意的问题 FAQ #### 一、引言 C++ 是一门功能强大且灵活的语言,但它的复杂性也带来了不少挑战。由 C++ 的创始人 Bjarne Stroustrup 所编写的这份 FAQ 不仅是学习 C++ 的宝贵资源,也是深入理解这门语言精髓的关键。本文将详细介绍该 FAQ 中提及的一些核心知识点,并结合实际应用场景进行解释。 #### 二、关键知识点详解 ##### 1. **为什么编译要花这么长的时间?** - **原因分析**: - **复杂的代码结构**:C++ 允许复杂的类层次结构、模板元编程等特性,这些都会增加编译时间。 - **预处理器的使用**:C++ 使用了大量的宏和预处理器指令,这些指令在编译前需要被处理,增加了编译的复杂度。 - **优化措施**: - **模块化**:通过将代码分解成更小的模块,减少每个模块之间的依赖关系。 - **预编译头文件**:使用预编译头文件可以显著减少编译时间。 - **增量编译**:只重新编译已更改的部分代码,而不是整个项目。 ##### 2. **为什么一个空类的大小不为0?** - **原理**:即使是一个空类也需要一定的内存空间来确保不同实例之间的区分。因此,C++ 标准规定空类至少占用 1 字节的空间。 - **应用场景**:在设计类时,即使是简单的包装类也需要考虑这一点,以免出现意料之外的行为。 ##### 3. **为什么成员函数默认不是 virtual 的?** - **设计哲学**:C++ 设计者认为大多数成员函数都不需要多态行为,因此默认非虚。这样可以提高性能并简化默认行为。 - **实践建议**:在需要多态行为时显式地声明成员函数为 `virtual`。 ##### 4. **为什么析构函数默认不是 virtual 的?** - **安全性考量**:如果一个类的析构函数不是虚拟的,则在删除派生类的对象时可能只调用了基类的析构函数,导致派生类中的资源未释放。 - **最佳实践**:对于包含指针或其他需要清理资源的类,应将析构函数声明为 `virtual` 并显式释放资源。 ##### 5. **为什么不能有虚拟构造函数?** - **逻辑限制**:构造函数用于初始化对象,而对象在其生命周期中只能被构造一次。虚拟构造函数会导致多态创建对象的概念冲突。 - **替代方案**:可以通过工厂模式或克隆模式实现类似的功能。 ##### 6. **为什么重载在继承类中不工作?** - **概念理解**:重载发生在同一作用域内的多个函数之间,而继承是不同类之间的关系。因此,在派生类中重新定义同名函数不会影响到基类中的函数。 - **解决办法**:使用 `virtual` 关键字声明基类中的函数,并在派生类中重写这些函数。 ##### 7. **我能够在构造函数中调用一个虚拟函数吗?** - **可行性分析**:在构造函数中调用虚拟函数会导致未定义行为,因为此时对象的完整类型还未确定。 - **规避策略**:避免在构造函数中调用虚拟函数。可以使用初始化列表进行必要的初始化。 ##### 8. **有没有“指定位置删除”(placement delete)?** - **背景介绍**:C++ 提供了 `placement new` 来在特定位置构造对象,但没有对应的 `placement delete`。 - **实现方式**:可以手动调用对象的析构函数来释放资源,然后清空内存。 ##### 9. **我能防止别人继承我自己的类吗?** - **技术手段**:可以通过将基类的构造函数声明为私有或受保护的方式来阻止继承。 - **设计考虑**:如果类被设计为非继承使用的,那么应该明确表明这种意图。 ##### 10. **为什么不能为模板参数定义约束(constraints)?** - **历史原因**:早期的 C++ 缺乏对模板参数约束的支持。 - **现代解决方案**:C++20 引入了 `concepts`,允许对模板参数施加限制。 ##### 11. **既然已经有了优秀的 qsort() 函数,为什么还需要一个 sort()?** - **性能与灵活性**:`qsort()` 是 C 标准库的一部分,而 `sort()` 是 C++ 标准库提供的更高效、更易于使用的排序算法。 - **使用场景**:`sort()` 支持容器和迭代器,更加符合 C++ 的设计哲学。 ##### 12. **什么是函数对象(function object)?** - **定义**:函数对象是一种可以像普通函数一样被调用的对象。 - **优势**:提供了更强大的封装性和可配置性。 ##### 13. **我应该如何对付内存泄漏?** - **预防措施**:使用智能指针如 `std::unique_ptr` 和 `std::shared_ptr` 来管理动态分配的内存。 - **检测工具**:利用 Valgrind、Visual Leak Detector 等工具来帮助检测内存泄漏。 ##### 14. **我为什么在捕获一个异常之后就不能继续?** - **异常安全**:在抛出异常后,对象可能处于不一致的状态,因此通常需要清理资源或恢复状态才能继续执行。 ##### 15. **为什么 C++ 中没有相当于 realloc() 的函数?** - **设计理念**:C++ 通过智能指针和容器等机制提供了一种更安全、更高效的方式来处理内存的动态调整。 ##### 16. **如何使用异常?** - **基本用法**:使用 `try` 块来尝试执行可能会抛出异常的代码,使用 `catch` 块来捕获并处理异常。 - **注意事项**:避免滥用异常处理作为控制流程的方式。 ##### 17. **怎样从输入中读取一个字符串?** - **标准库支持**:使用 `std::string` 类和 `std::getline` 函数从输入流中读取字符串。 ##### 18. **为什么 C++ 不提供 “finally” 的构造?** - **设计选择**:C++ 依靠 RAII(Resource Acquisition Is Initialization)原则来自动管理资源,减少了对 `finally` 构造的需求。 ##### 19. **什么是自动指针(auto_ptr),为什么没有自动数组(auto_array)?** - **概念解释**:`std::auto_ptr` 是一种智能指针,用于自动管理指向单一对象的指针。 - **设计考虑**:由于数组的特殊性质(不能直接复制),没有提供自动管理数组的智能指针。 ##### 20. **可以混合使用 C 风格与 C++ 风格的内存分派与重新分配吗?** - **兼容性问题**:虽然理论上可行,但在实践中可能会遇到各种问题,如内存对齐问题。 - **推荐做法**:尽量使用 C++ 的标准库和智能指针来管理内存。 ##### 21. **我为什么必须使用一个造型来转换 *void?** - **类型安全**:C++ 要求明确的类型转换,以避免潜在的类型错误。 - **示例**:从 `void*` 转换为其他类型的指针时,需要显式使用类型转换。 ##### 22. **我如何定义一个类内部(in-class)的常量?** - **语法**:可以直接在类声明中定义静态常量。 - **示例**:`class MyClass { static constexpr int c = 10; };` ##### 23. **为什么 delete 不会将操作数置 0?** - **设计决策**:`delete` 运算符的主要职责是释放内存,而不是修改指针。 - **安全提示**:程序员需要负责管理指针的有效性。 ##### 24. **我能够写 “void main()” 吗?** - **标准规定**:C++ 标准规定 `main()` 函数的返回类型应该是 `int`。 - **实践建议**:遵循标准定义 `int main()`。 ##### 25. **为什么我不能重载点符号,::,sizeof,等等?** - **语言限制**:这些符号是语言的关键部分,不能被重载。 - **设计考量**:保持语言的一致性和可预测性。 ##### 26. **怎样将一个整型值转换为一个字符串?** - **标准库支持**:使用 `std::to_string` 函数将整数转换为字符串。 ##### 27. **“int *p” 正确还是 “int * p” 正确?** - **语法差异**:这两种写法在语法上都是正确的,但习惯上更倾向于前者 `int *p`。 ##### 28. **对于我的代码,哪一种布局风格(layout style)是最好的?** - **个人偏好**:布局风格很大程度上取决于个人或团队的习惯。 - **推荐实践**:保持一致性,无论是个人还是团队都应该遵循统一的编码风格指南。 ##### 29. **我应该将 “const” 放在类型之前还是之后?** - **规范**:C++ 标准没有明确规定,但推荐将 `const` 放在类型后面,以提高可读性。 ##### 30. **使用宏有什么问题?** - **副作用**:宏在预处理阶段被展开,可能导致难以追踪的错误。 - **替代方案**:使用内联函数或模板来代替宏。 #### 三、结论 通过深入探讨 Bjarne Stroustrup 的 FAQ 中提到的关键知识点,我们不仅能够更好地理解 C++ 的设计哲学,还能学习到如何有效地使用这门语言来构建高质量的软件系统。无论你是初学者还是经验丰富的开发者,这份 FAQ 都值得反复研读,以便不断改进自己的编程技能。
剩余34页未读,继续阅读
- 粉丝: 16
- 资源: 19
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助