Подтвердить что ты не робот

Как убедиться, что функция вызывается только один раз

Предположим, что у меня есть функция с именем caller, которая вызовет функцию с именем callee:

void caller()
{
    callee();
}  

Теперь вызывающий вызов может быть вызван много раз в приложении, и вы хотите, чтобы вызываемый вызывался только один раз. (вроде ленивой инициализации), вы можете реализовать его с помощью флага:

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

Мое мнение для этого - это нужно больше кода, и ему нужно еще одну проверку в каждом вызове функции caller.
Лучшим решением для меня является следующее: (предположим, что callle возвращает int)

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

Но это не может справиться с тем, если callee возвращает void, мое решение использует выражение для запятой:

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

Но проблема заключается в том, что выражение для запятой не пользуется популярностью, и люди могут запутаться, когда видят эту строку кода, что вызывает проблемы для обслуживания.

Есть ли у вас хорошая идея, чтобы функция вызывалась только один раз?

4b9b3361

Ответ 1

потокобезопасна:

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

Ответ 2

Вы можете использовать это:

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

Ответ 3

Скрыть функцию можно с помощью указателя функции.

static void real_function()
{
  //do stuff

  function = noop_function;
}


static void noop_function()
{

}

int (*function)(void) = real_function;

Звонящие просто вызывают function, который будет выполнять работу в первый раз, и ничего не делать при последующих вызовах.

Ответ 4

Ваш первый вариант с булевым флагом bFirst - это не что иное, как экспликация в ручном исполнении того, что компилятор сделает для вас в ваших других вариантах.

Другими словами, в типичной реализации во всех вариантах, которые вы представляли до сих пор, будет дополнительная проверка для булевого флага в сгенерированном машинного кода. Активация всех этих вариантов будет одинаковой (если это ваша забота). Дополнительный код в первом варианте может выглядеть менее изящным, но для меня это не очень важно. (Оберните его.)

В любом случае, то, что у вас есть в качестве первого варианта, в основном, как это обычно делается (пока вы не начнете разбираться с такими проблемами, как многопоточность и т.д.).

Ответ 5

Вдохновленный некоторыми людьми, я думаю, что просто использовать макрос, чтобы обернуть выражение запятой, также будет ясно:

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