7

多年前,我认为 C 与 C++ 相比绝对是纯粹的,因为编译器无法生成任何您无法预测的代码。我现在相信反例包括volatile关键字和内存屏障(在多处理器编程或内存映射硬件设备的设备驱动程序中,纯汇编语言比 C 编译器的优化更纯粹)。

目前我正在尝试列举 C++ 编译器可以做的不可预测的事情。我对 C++ 的主要抱怨是编译器会隐式实例化临时对象,但我相信这些情况都是可以预料的。我想到的案例是:

  • 当一个类为自身以外的类型定义复制构造函数时,不使用explicit关键字
  • 当一个类定义一个重载的转换运算符时: operator ()
  • 当函数通过值而不是通过引用接受对象时
  • 当函数按值而不是按引用返回对象时

还有其他人吗?

4

3 回答 3

2

12.2 临时对象

1 类类型的临时对象在各种上下文中创建:将右值绑定到引用 (8.5.3)、返回右值 (6.6.3)、创建右值的转换 (4.1、5.2.9、5.2.11、5.4 )、抛出异常 (15.1)、进入处理程序 (15.3) 以及在某些初始化中 (8.5)。

4 有两种情况,其中临时对象在与完整表达式结尾不同的点被销毁。

事实上我建议看看整个 12.2

目前我正在尝试列举 C++ 编译器可以做的不可预测的事情。我对 C++ 的主要抱怨是编译器会隐式实例化临时对象,但我相信这些情况都是可以预料的。

编译器不会隐式创建临时对象——它遵循标准。当然,除非您调用未定义的行为。请注意,有一种称为复制省略和返回值优化的东西,实际上可能会减少原本会创建的临时对象的数量。

于 2010-02-08T14:36:05.613 回答
2

我想“不可预测”的意思是“符合标准但与程序员在编写代码时所期望的不同”,对吧?

我想您可以从代码中看到正在实例化或复制对象的位置,即使它可能并不明显。不过可能很难理解。

有些东西只是由(全部?)编译器供应商以某些方式实现的,但它可以以不同的方式完成。例如,后期绑定(也就是调用重载的虚方法)通常在后台使用函数指针来实现。这可能是最快的方法,但我想它可以以不同的方式完成,这将是出乎意料的。我不知道任何编译器,但它的作用不同。

在 C++ 过于复杂的意义上,很多东西是出乎意料的——几乎没有人能理解完整的语言。所以意外也取决于你的知识。

于 2010-02-08T14:28:44.940 回答
0

An interesting link about common pitfalls related to this subject:

http://www.gotw.ca/gotw/002.htm

于 2010-02-08T17:13:24.543 回答