【问题标题】:Should one keenly & consciously attempt to postpone variable definitions as long as possible?是否应该敏锐而有意识地尝试尽可能长时间地推迟变量定义?
【发布时间】:2011-06-21 17:30:37
【问题描述】:

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

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

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

这一切似乎都是合乎逻辑的,而且确实是一种很好的做法。来自c 背景,我倾向于在功能块的开头声明所有变量。也许它只是c 背景,但我也觉得将所有声明放在一个函数中的一个位置提供了简单和更好的可读性。

所以问题是你们中有多少人在日常编程中真正遵循了这种做法,或者尝试遵循这种做法只是一种矫枉过正。

【问题讨论】:

    标签: c++ performance


    【解决方案1】:

    Scott Meyers 的建议(和往常一样)非常好,您应该遵循它。我已经这样做了二十年了,我不喜欢 Java 已经采用 C 的方式来做这件事。

    【讨论】:

    • 我同意我什至在 Q 中提到的,只是我倾向于将所有声明都放在一个地方,对于我来自 c 背景的我来说,这样我认为它们更具可读性。
    • @Als:我认为它“更习惯”而不是“更易读”。我想你会同意我的观点,从理论上讲,阅读一个变量定义说“请记住我一会儿,我会回来的”实际上比阅读一个定义更少可读立即使用。正如我在回答中所说,当您习惯了这一点后,您会惊讶于这在多大程度上简化了代码的阅读
    【解决方案2】:

    我当然愿意。确实需要对新习惯进行一些适应(我自己来自其他语言,我知道你的意思),但是一旦你在那里,它就方便多了。除了您提到的之外,我还看到了另外 2 个好处:

    1. 提高了可读性:您需要更少的“缓存”来记住函数范围中使用的变量。每一段代码都定义了自己的变量。

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

    【讨论】:

    • 我认为如果#1是函数太长的问题。
    • @Billy:也许吧,但无论如何,当一个变量被定义为最接近它的用途时,它更具可读性,比如在if/while等中,不是吗?
    • 我认为这是见仁见智的问题。
    【解决方案3】:

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

    【讨论】:

    • @Als:用 C99 或更高版本编写的任何内容。
    • 当然,如果您正在编写嵌入式 C 代码,那么您可能(取决于编译器)希望在函数级别声明变量以减少在堆栈上分配变量的开销。 (易于测试,只需尝试两种方式,看看本地块级别是否生成比函数级别版本更大的代码。)在嵌入式世界中,每个字节都很重要。也就是说,我仍然希望尽可能延迟声明变量。
    • @Tom:如果你将声明和语句交织在一起,真的有编译器愚蠢到可以让函数变慢吗?
    • 在“函数级别”声明的变量分配在堆栈上。
    • 想象一个只有十几个堆栈帧空间的环境。编译器可能会选择不预先为所有变量分配足够的空间[通过单个 sp += 8],而是根据需要逐个进行 [通过初始 sp += 4,然后是 sp +=4 几个后面的指令] 这样在函数之间有尽可能多的额外堆栈空间。但这会增加函数的大小,这本身就是一个不同的问题。另外,由于我们不是在谈论具有 30 条指令流水线的 Pentium,因此速度略有不同。
    【解决方案4】:

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

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

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

        将您的 C 习惯用作 C++ 的指南并不是一个好主意。相同的规则不适用。

        【讨论】:

          【解决方案7】:

          我两个都做。

          我的意思是,按照 Scott Meyers 的指导方针,我只在最后一刻定义变量。当这意味着它们遵循一个左大括号时,我将此视为函数的这一部分可能需要提取到它自己的函数的信号。提取新函数后,这些局部变量也随之被提取 - 它们出现在函数的顶部。

          【讨论】:

            【解决方案8】:

            我通常会延迟定义一个变量,直到它被使用之前,大致按照 Scott 的建议。

            然而,IMO,如果“需要它的地方”确实与“块的开头”(甚至“函数的开头”)不同 很多,那么您的机会是相当公平的'正在编写可能比理想更大的单个函数,并且您的代码可能会受益于被分解成更小、更简单且更易于理解的部分。

            【讨论】:

              【解决方案9】:

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

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

              有时可以通过重构函数来消除这些考虑,但有时不会。

              【讨论】:

                【解决方案10】:

                我也这样做。使用现代 IDE 并没有太大帮助,但是如果您在使用它的位置附近有声明,则无需搜索即可查看类型。

                【讨论】:

                  猜你喜欢
                  • 2014-08-30
                  • 1970-01-01
                  • 2014-04-05
                  • 1970-01-01
                  • 2012-11-26
                  • 2012-03-26
                  • 2014-06-22
                  • 1970-01-01
                  • 2014-05-16
                  相关资源
                  最近更新 更多