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

在函数中使用静态变量与从调用者传递变量

c++
  •  0
  • Patrick  · 技术社区  · 15 年前

    我有一个生成各种类型线程的函数,其中一种线程类型需要每x秒生成一次。我现在的情况是这样的:

    bool isTime( Time t )
    {
         return t >= now();
    }
    
    void spawner()
    {
        Time t = now();
        while( 1 )
        {
             if( isTime( t ) )//is time is called in more than one place in the real function
             {
                 //launchthread and recalculation of t only happens once in real function
                 launchthread()
                 t = now() + offset;
             }
        }
    }
    

    bool isTime()
    {
        static Time t = now();
        if( t >= now() )
        {
             t = now() + offset;
             return true;
        }
        return false;
    }
    
    void spawner()
    {
         while( 1 )
         {
             if( isTime() )
                 launchthread();
         }
    }
    

    我认为第二种方法更简洁,但我通常避免静态,就像避免全局数据一样;有人对不同的款式有什么看法吗?

    6 回复  |  直到 8 年前
        1
  •  4
  •   Marcelo Cantos    15 年前

    除了我在对问题的评论中提到的问题外,你应该避免像瘟疫这样的聪明把戏。第一个表单(在修复错误之后)更干净,更容易理解。第二种形式是OTOH,它给人的印象是任务是 t 还有测试 t >= now()

        2
  •  3
  •   Suma    15 年前

    这种方法的一个缺点是 static Time t

    想象一下如果你有两个独立的 spawner 他用了一个 .

    如果您更喜欢第二种形式,则可以实现非常类似的效果,但不必使用静态:

    bool isTime(Time &t)
    {
        if( t >= now() )
        {
             t = now() + offset;
             return true;
        }
        return false;
    }
    
    void spawner()
    {
        Time t = now();
        while (1)
        {
         if( isTime(t) )
              launchthread();
        }
    }
    
        3
  •  2
  •   xtofl Adam Rosenfield    15 年前

    “第二种方法”有一个更容易阅读的方法 spawner 功能。但是,通过使用成员变量i.s.o.全局状态,可以使其具有相同的可读性。

    struct Spawner {
        time when_to_wakemeup;
        timediff step;
    
        Spawner( timediff astep ): when_to_wakemeup(Now()+astep),step(astep){
        }
    
    
        // this is the member-function equivalent of your "spawner" function
        void keep_spawning() {
    
            while(true) {
                while( Now() < when_to_wakemeup ) Wait();
                when_to_wakemeup += step;
                spawn_one();
            }
         }
    
         void spawn_one() {
            //... whatever you need
         }
      };
    

    使用这样的类,您可以创建许多“产卵者”,而不必费心保护您的全局状态:

      Spawner very_often( .5 );
      very_often.keep_spawning();
    
        4
  •  1
  •   Frerich Raabe    15 年前

    我建议使用第一个版本,因为它更易于测试。输入和输出清晰可见,您可以通过向其中输入有趣的时间值来很好地执行边界测试。如果您有引用全局和/或静态数据的代码,这是不可能的。

        5
  •  1
  •   Puppy    15 年前

    如果您有一个提供线程的库,那么它还应该提供计时器。例如,WinAPI提供了每X秒调用一个给定函数的功能。这可能是最好的解决办法。

        6
  •  0
  •   Michał Trybus    15 年前

    static Time t 方法对代码的其余部分隐藏时间。如果这是您的意图(您不需要在其他地方使用全局时间和变量 t 静态方法在我看来更整洁。

    但是,如果您的程序是一个模拟,其中当前时间对程序的所有部分都是至关重要的,那么我个人会选择不隐藏时间变量,并实现它 isTime 就像第一段代码一样。