【问题标题】:C++ Initialize Static ArrayC++ 初始化静态数组
【发布时间】:2017-02-06 14:16:19
【问题描述】:

我不确定这是否可能。从我看到的所有示例中,数组是在{ } 括号内定义的,但就我而言,这不太可能。

我想要做的是将它保留在我的绘图函数中,以绘制多个逐渐增大的圆圈。

我使用调试器得到的是每次循环命中时都会重置静态数组。

我也尝试过类似static Rect rc[5] = {}

void fun_called_every_five_seconds() {
     static Rect rc[5];

     for (int i = 0; i < count; i++) {
         int x = rand()%400;
         int y = rand()%400;
         int r = rand()%200;
         rc[i] = Rect (x,y,r,r);
     }

     rc[0].X += 50;


     // I check value of rc[0].X right here
 }

【问题讨论】:

  • 代码在什么上下文中?代码和static 数组是否都在函数内,或者static 是否在命名空间范围内?请给minimal reproducible example
  • @KABoissonneault 添加了示例。从计时器中,该函数每 5 秒调用一次。
  • 每次调用函数时都会执行for循环。
  • @JohnnyMopp 因为在更大的范围内不需要这个数组(下一个选项是全局的?),有没有办法只填充一次数组?我认为通常你可以这样做,比如static int = 5;
  • static int s_something = 5; 之所以有效,是因为它正在初始化,您无法重新初始化,因此如果在其他地方重新定义了该值,则该值不会“切换回”。

标签: c++ arrays static


【解决方案1】:

每次循环命中时都会重置静态数组

是的,您的循环显式重置了静态数组。

最小的变化是只运行一次初始化循环:

void for_fun_called_every_five_seconds() {
    static Rect rc[5];
    static bool init = false;
    if (!init) { // this only happens once
        init = true;
        for (int i = 0; i < count; i++) {
            int x = rand()%400;
            int y = rand()%400;
            int r = rand()%200;
            rc[i] = Rect (x,y,r,r);
        }
    }

    rc[0].X += 50;

    // I check value of rc[0].X right here
}

但这很丑陋,而且不必要地难以推理。喜欢类似的东西

class Circles {
    Rect rc[5];
public:
    Circles() {
        for (int i = 0; i < count; i++) {
            int x = rand()%400;
            int y = rand()%400;
            int r = rand()%200;
            rc[i] = Rect (x,y,r,r);
        }
    }
    void for_fun_called_every_five_seconds() {
        // should this also be in a loop,
        // ie. each rc[i] gets increased?
        rc[0].X += 50;
        // I check value of rc[0].X right here
    }
};

【讨论】:

  • 很好,该解决方案有效。如果我的程序(游戏)还没有因课程而陷入困境,我会选择后者。
  • 如果您想要更好/便携的随机数生成,可能还想使用&lt;random&gt; 中的设施
  • @EvanCarslake:您没有创建新课程,因为您已经用完了每个项目的任意课程配额?认真的吗?
  • 请注意,第一个解决方案不是线程安全的。另外,@EvanCarslake,我认为没有太多的课程。 C++ 中的类可以是“零开销”抽象,这意味着它们是供您使用的免费工具,而不会影响程序的执行。如果一个类可以帮助你在一个简单的界面中隐藏一些复杂的逻辑,那么你应该总是这样做。
  • @llnspectable 好吧,我的意思是我的主要绘图功能非常庞大,我希望这些特定的绘图部分在其中紧凑。例如,这是一个在每个不同级别上都发生变化的动画。我想我可以创建一个类来处理所有这些......
【解决方案2】:

您可以拆分代码并将数组初始化放在其他地方:

auto make_rect_array() {
    std::array<Rect, 5> rc;

    for (int i = 0; i < count; i++) {
        int x = rand()%400; // you may want better random
        int y = rand()%400;
        int r = rand()%200;

        rc[i] = Rect (x,y,r,r);
    }

    return rc;
}

然后,只需在你的函数中调用它:

void fun_called_every_five_seconds() {
    static auto rc = make_rect_array();

    rc[0].X += 50;
    // I check value of rc[0].X right here
}

这样,您不会在代码中引入额外的分支,它看起来更干净并且是线程安全的。

【讨论】:

    【解决方案3】:

    这里没有什么好惊讶的。每次调用一个函数时,它的所有代码都会从它的参数中执行。 这里唯一的例外是 static 变量的初始化,它保证在程序的生命周期内只运行一次(自 C++11 以来也是线程安全的)。 变量的初始化仅发生在其定义期间,在此上下文中您为变量命名的那一行。之后的所有代码只是简单地“改变”你的变量以赋予它你想要的值:它不是初始化。

    这里有两种解决方案。要么使用 std::call_once 和 lambda(请参阅 http://en.cppreference.com/w/cpp/thread/call_once),以使“初始化”代码只运行一次。 或者您以某种方式将所有代码放在变量定义的一行中。对于 C 样式的数组可能会很复杂,但对于 std::array 则不然,它可以很容易地从函数中返回并用于初始化 std::array

    std::array<Rect, 5> initialize_rc() {
       std::array<Rect, 5> rc;
    
       for (int i = 0; i < count; i++) {
           int x = rand()%400;
           int y = rand()%400;
           int r = rand()%200;
           rc[i] = Rect (x,y,r,r);
       }
    
       return rc;
    }
    
    void for_fun_called_every_five_seconds() {
       static std::array<Rect, 5> rc = initialize_rc();
    
       rc[0].X += 50;
    
       // I check value of rc[0].X right here
    }
    

    【讨论】:

      【解决方案4】:

      另一个答案很好,只要整个事情不必是线程安全的。

      如果初始化必须是线程安全的,那么除了将所有内容都放入声明之外别无选择。

      但是,可以使用辅助类来最小化输入:

      class RandomRect : public Rect {
      
      public:
          RandomRect() : RandomRect(rand() % 400, rand() % 400, rand % 200) {}
          RandomRect(int x, int y, int r) : Rect(x, y, r, r) {}
      };
      
      // ... Then, initialize the static array as follows:
      
      static Rect rc[5]={RandomRect(), RandomRect(), RandomRect(),
                         RandomRect(), RandomRect()};
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-04
        • 2013-04-13
        • 1970-01-01
        • 2011-05-25
        • 2017-08-26
        • 2010-11-25
        相关资源
        最近更新 更多