是否应该敏锐而有意识地尝试尽可能长时间地推迟变量定义?

Should one keenly & consciously attempt to postpone variable definitions as long as possible?

本文关键字:长时间 尽可能 推迟 变量 定义 是否 有意识      更新时间:2023-10-16

在他的书Effective C++ Scott Meyers中提出了一个有趣的指导原则,

第26项:尽可能推迟变量定义。它增加了程序的清晰度&提高程序效率

他提出的支持上述观点的论点是,每当一个变量被创建或破坏时,我们都会产生一些构建成本;变量的销毁
我们可能有多个控制流,其中我们可能从函数返回,而不使用早期定义的变量(在函数的开头)&因此可能不必要地产生未使用变量的创建成本。

这一切似乎都是合乎逻辑的;这确实是一个很好的做法。来自c背景的我倾向于在函数块的开头声明我的所有变量。也许这仅仅是c背景,但我也觉得在函数中的一个位置拥有所有声明可以提供简单的&更好的可读性。

因此,问题是,在日常编程中,你们中有多少人真的遵循了这样的做法,或者试图遵循这样的做法只是过度了。

Scott Meyers的建议(像往常一样)非常好,你应该遵循它。我已经做了20年了,我不喜欢Java采用C语言来做这件事。

我当然会。这确实需要一些适应新习惯的适应(我自己也来自其他语言,我知道你的意思),但一旦你到了那里,它就会方便得多。除了你提到的,我还看到了另外两个好处:

  1. 提高可读性:你需要更少的大脑"缓存"来记住函数范围中使用的变量。每一个小小的代码都定义了自己的变量。

  2. 初始化:一个非常重要的原则是,变量应尽可能定义为初始化。在功能开始时并不总是能够知道初始化值

即使在现代C中,也应该推迟声明,直到可以使用合理的值进行初始化。斯科特是老师,我们只是追随者。。。

该规则一直是我工作过的所有编码指南的一部分。有一些例外(例如,如果变量将使用流中的输入进行初始化),但通常情况下,应将变量定义为尽可能接近首次使用点,并定义为使用有效值进行初始化。

I几乎总是尽可能长时间地延迟变量声明(例如,维护现有代码时除外)。它允许变量作用域具有更大的局部性,从而更容易理解代码(清楚地显示变量的使用位置)。它允许我在声明时立即初始化变量,而不是让它未初始化或给它一个伪状态。对于没有默认构造函数的类,不能尽早声明它们,因为您还不知道构造函数参数。

我将在很大程度上忽略更好的可读性声明,但我不同意。C89规则是由于编译器的限制,而不是为了可读性(C99更改了规则,允许在任何地方声明变量)。

在C中,声明未初始化的变量是没有代价的,因为所有变量都是POD,所以您可以在函数顶部声明所有内容,然后再初始化它。在C++中,有些类型具有非平凡的默认构造函数,因此您需要付费立即初始化它们,因此最好推迟到需要它们时再进行初始化。

用你的C语言习惯来指导C++不是一个好主意。同样的规则不适用。

我两者都做。

我的意思是,按照Scott Meyers的指导方针,我只在最后可能的时刻定义变量。当这意味着它们遵循一个大括号时,我认为这是一个信号,表明函数的这一部分可能需要提取到它自己的函数中。一旦提取出新函数,这些局部变量就会随之提取出来,并出现在函数的顶部。

我通常会延迟定义变量,直到它被使用之前,大致如Scott所建议的那样。

然而,IMO,如果"需要它的地方"真的与"块的开始"(甚至"函数的开始")有很大的不同,那么你编写的单个函数可能比理想的要大,你的代码可能会从更小、更简单、更容易理解的碎片中受益。

我经常对变量定义进行逻辑分组,而不是根据需要定义每个定义。这可能意味着同时位于函数的顶部,也可能不是。

举个例子,假设我有一个计算三个统计数据的函数。如果其中两个统计数据需要一些预处理[除了简单的初始化],但第三个不需要,我仍然会在函数开始时将这三个统计数据分组在一起,因为它们是一个逻辑组。但我不会定义同时用于错误检查的随机循环条件,因为它与其他三个条件无关。

有时有一些方法可以重构函数以消除这些考虑因素,但有时不是。

我也这样做。对于现代IDE来说,这并没有那么大的帮助,但如果您在使用声明的地方附近有声明,则无需搜索即可查看类型。