代码之家  ›  专栏  ›  技术社区  ›  onaclov2000

常量的好处

  •  14
  • onaclov2000  · 技术社区  · 16 年前

    我知道常数的一大好处是,你不必检查和更新到处都在使用常数的代码。这很好,但是假设你没有显式地将它声明为常量。采用一个碰巧没有改变的变量并使其成为常量有什么好处?这会节省处理和/或代码大小…等等?

    14 回复  |  直到 15 年前
        1
  •  25
  •   swestrup    16 年前

    如果您将一个变量声明为常量,那么优化器通常可以通过“常量折叠”来消除它,从而既加快了程序的速度,又节省了空间。举个例子,考虑一下:

    var int a = 5;
    const int b = 7;
    ...
    c = process(a*b);
    

    编译器最终将创建一条指令,将a乘以7,并将其传递给“process”,将结果存储在c中。但是在这种情况下:

    const int a = 5;
    const int b = 7;
    ...
    c = process(a*b);
    

        2
  •  21
  •   3Dave    15 年前

        3
  •  7
  •   3Dave    16 年前

    这在很大程度上取决于你的优化器有多好。

    一个好的优化器将在编译期间用文本值替换常量引用。这节省了处理器周期,因为生成的机器代码使用的是即时值,而不必从内存中加载值。

    一些 优化器将识别一个值在声明之后没有被修改,并将它转换为一个常量。不要依赖这种行为。

    而且,只要有可能,您的代码应该强制执行您在开发过程中所做的假设。如果一个“变量”永远不应该被更改,那么将它声明为一个常量将有助于确保您自己和以后出现的任何其他开发人员都不会无意中修改一个“常量”。

        4
  •  4
  •   jball    16 年前

    将一个变量标记为常量表明了您作为程序员的意图,即无论何时在代码执行期间访问它,它都将是一个一致的值。将其视为一种文档形式,也可以使编译器参与到设计中。

        5
  •  3
  •   Vincent Ramdhanie    16 年前

    正如您所指出的,将不变的变量更改为显式常量可能没有任何直接的好处。然而,在分析一个程序时,要做的一个检查是查看变量的声明点到变量的引用点。因此,诸如在声明之前被访问的变量,或者在引用之前被设置和重置的变量等指标可能会指示bug。

    对于使用您的代码的其他开发人员也是如此。他们可能无意中设置了一个变量,而您可能没有意识到。声明常量可以避免这些类型的错误。

        6
  •  3
  •   Simon Wright    16 年前

    System 您将发现(在x86机器上)

    type Bit_Order is (High_Order_First, Low_Order_First);
    Default_Bit_Order : constant Bit_Order := Low_Order_First;
    

    所以那是给定的

    case System.Default_Bit_Order is
       when System.High_Order_First =>
          --  Big-endian processing
       when System.Low_Order_First =>
          --  Little-endian processing
    end case;
    

    -O2 我想。

    这两个分支都必须是可编译的——这是一个优化,而不是 #ifdef 处理。

        7
  •  2
  •   itsmatt    16 年前

    一个好处是,如果它真的是一个常量,您不会意外地更改它。这个常数让你以后不会把事情搞砸。作为一个变量,任何人都可以在以后更新代码时修改它。

    应该清楚哪些价值观永远不会改变,哪些价值观可以改变。不断强化你的意图。


        8
  •  2
  •   Vlad    16 年前

    除了已经说过的以外,将变量声明为常量可以为优化器提供更多的自由度。它可以消除读取它的值,它可以消除创建临时副本的需要,它可以消除变量本身(这对于数值常量尤其如此)。

    常量的另一个大用例是常量对象。拥有一个常量对象(或者在函数中提供对常量对象的引用)可以确保对象没有被修改,只有方法(调用 const 方法)。然而,对于C++,这是真的,我不确定在艾达中是否同样的概念是有效的。

        9
  •  2
  •   Jay    16 年前

    根据语言的不同,另一种可能性是编译器可以在多线程环境中进行一些优化,而这些优化在其他情况下是不可能的。就像你说:

    int b=x*f;
    int c=y*f;
    

    在多线程环境中,如果f是一个变量,编译器可能必须在第二个操作之前重新生成f。如果f是一个常量,并且编译器知道它仍在寄存器中,则不需要重新加载。

        10
  •  2
  •   T.E.D.    16 年前

    当然,对于C和Ada这样的语言,编译器会将常量中的值直接放入汇编指令中,这意味着除了运行程序所需的内容外,不需要交换寄存器或从内存中读取内容。这意味着两件事:一是速度(在许多应用程序中可能不太明显,除非它们是嵌入式的),二是内存使用(程序的最终二进制大小和运行时内存占用)。

    其次,正如ITSMAT和JBARL所述,它使您可以逻辑地将项目视为常数配置项而不是“变量”;尤其是在高级编程语言和解释语言中。

        11
  •  2
  •   mat_geek    16 年前

    还有另一个好处,堆栈和数据段的大小。

    考虑:

    function Recurser(i : Integer) return Integer is
      ia : array(0..9) of Integer
              := (1, 2, 3, 4, 5, 6, 7, 8, 9, 1000);
      r : Integer;
    begin
       if i = 0 then return 0; end if;
       r := ia(i mod 10);
       return r + Recurser(i - 1);
    end;
    

    每次该函数递归时,都会在堆栈上创建一个320字节的结构。但由于a的值不变,堆栈将增加以保持一个常量变量。这在具有小堆栈的嵌入式平台上非常重要。

        12
  •  2
  •   T.E.D.    15 年前

    这并不是Ada特有的问题。

    常数对变量的一般好处:

    • 通知编译器在优化时可以假定值不会更改。

    Ada特定益处:

    • 对于数值常量,不必指定类型(命名的数字)。如果用这种方式声明它,它将可以用在任何表达式中。如果改用变量,则只能在该变量的 .

    Seconds_Per_Minute : constant := 60;
    Secs_Per_Min       : Integer  := 60;
    
    type Seconds_Offset is 0 .. Integer'last; --'
    
    Min1, Secs1 : Integer;
    Min2, Secs2 : Seconds_Offset;
    
    ...
    --// Using the named number, both of these compile no problem.
    Secs1 := Min1 * Seconds_Per_Minute;
    Secs2 :=  Min2 * Seconds_Per_Minute;
    
    --// The second line here gives an error, since Integer is a 
    --// different type than Seconds_Offset.
    Secs1 := Min1 * Secs_Per_Min;
    Secs2 := Min2 * Secs_Per_Min;
    
        13
  •  1
  •   Tuomas Pelkonen    16 年前

    常量通常存储在只读内存中,这样可以防止在执行过程中更改常量,访问它们的速度可能更快,或者至少与访问RAM的速度一样快。

        14
  •  0
  •   Leniel Maccaferri    16 年前

    常量与变量的一个重要区别在于,一旦一个值被赋予一个常量,它就不能随之改变。