如何确保只调用一次函数

时间:2010-11-13 16:01:16

标签: c++

假设我有一个名为caller的函数,它将调用一个名为callee的函数:

void caller()
{
    callee();
}  

现在可以在应用程序中多次调用调用者,并且您希望确保只调用一次调用者。 (一种延迟初始化),你可以使用一个标志来实现它:

void caller()
{
    static bool bFirst = true;
    if(bFirst)
    {
        callee();
        bFirst = false;
    }
}

我的意见是它需要更多代码,并且每次调用函数调用者时都需要再检查一次 对我来说更好的解决方案如下:(假设被调用者返回int)

void caller()
{
    static int ret = callee();
}  

但如果callee返回void,则无法处理这种情况,我的解决方案是使用逗号表达式:

void caller()
{
    static int ret = (callee(), 1);
}  

但问题在于,逗号表达式并不常用,人们在看到这行代码时可能会感到困惑,从而导致维护问题。

你有什么好主意确保只调用一次函数吗?

5 个答案:

答案 0 :(得分:19)

你可以用这个:

void caller()
{
    static class Once { public: Once(){callee();}} Once_;
}

答案 1 :(得分:12)

主题安全的:

    static boost::once_flag flag = BOOST_ONCE_INIT;
    boost::call_once([]{callee();}, flag);  

答案 2 :(得分:7)

您可以通过函数指针隐藏该函数。

static void real_function()
{
  //do stuff

  function = noop_function;
}


static void noop_function()
{

}

int (*function)(void) = real_function;

来电者只需拨打function即可完成第一次工作,并且不会对任何后续电话执行任何操作。

答案 3 :(得分:2)

你的第一个带有布尔标志bFirst的变体只不过是 explict 手动实现编译器将为你做的暗示在你的其他变种中。

换句话说,在你所提出的所有变种中的典型实现中,将在生成的机器代码中另外检查一个布尔标志。所有这些变体的性能都是相同的(如果这是您的关注)。第一个版本中的额外代码可能看起来不那么优雅,但这对我来说似乎并不重要。 (包裹它。)

无论如何,你的第一个变体基本上是如何正常完成的(直到你开始处理多线程等问题。)

答案 4 :(得分:0)

受到一些人的启发,我认为使用宏来包装逗号表达式也会使意图明确:

#define CALL_ONCE(func) do {static bool dummy = (func, true);} while(0)