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

时间:2010-06-03 10:21:57

标签: c++

我有一个产生各种类型线程的函数,其中一个线程类型需要每隔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 个答案:

答案 0 :(得分:4)

除了我在问题评论中提到的问题,你应该避免像瘟疫一样聪明的伎俩。第一种形式(修复bug之后)更清晰,更容易理解。第二种形式,OTOH,给人的印象是,t的分配和t >= now()的分配紧接着发生在彼此之后,他们在意识到它的静态,然后必须试图让算法第二次。

此外,您永远不能重置第二个功能或从多个线程使用它。

答案 1 :(得分:3)

static Time t方法的一个缺点是静态变量的函数通常不是可重入的(因此不是线程安全的) - 这对您来说可能是也可能不是问题。

想象一下,如果您有两个独立spawner并使用static Time t会发生什么。

如果你更喜欢第二种形式,你可以实现非常相似的东西,但不使用静态:

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();
    }
}

答案 2 :(得分:2)

“第二种方式”具有更易于阅读的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
     }
  };

有了这样的课程,你可以创建一些“Spawners”,而不必费心去保护你的全球状态:

  Spawner very_often( .5 );
  very_often.keep_spawning();

答案 3 :(得分:1)

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

答案 4 :(得分:1)

如果你有一个提供线程的库,它也应该提供定时器。例如,WinAPI提供每X秒调用给定函数的功能。这可能是最好的解决方案。

答案 5 :(得分:0)

static Time t方法隐藏了其余代码的时间。如果这是你的意图(你不需要在其他地方使用全局时间而变量t只是为了决定是否产生线程),那么静态方法似乎更适合我。

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

相关问题