【问题标题】:static const cached result静态常量缓存结果
【发布时间】:2016-12-22 04:06:26
【问题描述】:

在下面的例子中 -

#include <iostream>

int someMethod(){
  static int a = 20;
  static const int result = a + 1;
  ++a;
  std::cout << " [" << a << "] ";
  return result;
}

int main(){
  std::cout << someMethod() << "\n";
  std::cout << someMethod() << "\n";
  std::cout << someMethod() << "\n";
}

输出为 -

[21] 21

[22] 21

[23] 21

阻止result 值在对同一函数的后续调用中被修改的原因是什么?我也打印了变量a 的输出,它肯定是递增的,而且由于它也是静态的,所以同一个方法不能存在多个副本。

IDEONE - COMPILER OUTPUT

【问题讨论】:

  • 原因是static const?

标签: c++ c++11 static constants


【解决方案1】:

由于result是静态的,所以在运行时只会初始化一次。所以不管你调用多少次someMethod(),下面这行代码只会执行一次

 static const int result = a + 1; 

【讨论】:

  • @George 是的,我的意思是 initialize.static 变量只初始化一次。对吧?
  • @乔治。你能解释一下原因吗?
  • @George 嗯?函数局部静态的初始化仅在第一次控制流过声明时发生。那么为什么要一遍又一遍地评估初始化器呢?
  • @George 不是。请删除您的 cmets 以减少此处的混淆。
【解决方案2】:

这里的const只是从真正的原因打扰读者。这段代码的执行完全相同。

int someMethod(){
  static int a = 20;
  static int result = a + 1;
  ++a;
  std::cout << " [" << a << "] ";
  return result;
}

真正的原因是= 符号可以表示 C++ 中的两种不同操作:赋值(每次执行)或初始化(仅在创建变量时执行)。当它是变量的声明/定义的一部分时的区别。

在正常情况下(不是 bloc 静态变量),两者都是等价的,因为每次声明它的块运行时都会创建一个自动变量(或者至少编译器必须确保所有行为 就像 就是这样)。

但是对于块静态变量,初始化只发生一次,这里变量结果被初始化为21,它的值永远不会改变。

这些变体会有很大不同

int someMethod(){
  static int a = 20;
  static int result;
  result = a + 1; // assignation: result will see its value change with the value of a
  ...

int someMethod(){
  static int a = 20;
  static const int result = a;
  result = a + 1;  // Error modification of a const declared variable

【讨论】:

  • 一个很好的答案,但在最后一个代码块的最后两行中有两个小错误。 'static const int result' 必须初始化,因为它是 const 并且在下一行中修改 'result' 也会导致编译器错误,而不是未定义的行为。
【解决方案3】:

静态提示编译器不要重新初始化变量,除了强制编译器在程序的数据段上分配变量的值。

【讨论】:

    【解决方案4】:

    正如其他人所解释的,result 是一个static 变量,因此它仅在第一次执行someMethod() 时才被初始化。

    result也是const,所以第一个赋值为

    static const int result = a + 1;
    

    在程序的后续执行中保持不变。

    我想您期望使用 reference 可以实现某些目标;如果你修改前一行如下

    static const int & result = a;
                     ^
    // note the & ---|
    

    你将result链接到a并修改a你修改result,输出是

    [21] 21
    [22] 22
    [23] 23
    

    问题是您可以将一个变量引用到另一个变量,而不是表达式;所以你可以将result链接到a,而不是a+1(不是a+1的动态值);所以下面一行

    static const int & result = a + 1;
    

    编译但是(如果我没记错的话)将result链接到存储(在someMethod()的第一次执行时)表达式a + 1的结果的未命名变量,所以输出再次

     [21] 21
     [22] 21
     [23] 21
    

    【讨论】:

    • 我觉得a + 1这个版本是合法的(不过当然是指你说的固定值)
    • @M.M - 抱歉,但是...a 也是 static,那么为什么引用会在后续调用函数时悬空?
    • 你说得对,我在想象一个版本,其中 a 出于某种原因是一个函数参数
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-18
    • 2012-08-18
    • 1970-01-01
    相关资源
    最近更新 更多