Ответ 1
потокобезопасна:
static boost::once_flag flag = BOOST_ONCE_INIT;
boost::call_once([]{callee();}, flag);
Предположим, что у меня есть функция с именем 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);
}
Но проблема заключается в том, что выражение для запятой не пользуется популярностью, и люди могут запутаться, когда видят эту строку кода, что вызывает проблемы для обслуживания.
Есть ли у вас хорошая идея, чтобы функция вызывалась только один раз?
потокобезопасна:
static boost::once_flag flag = BOOST_ONCE_INIT;
boost::call_once([]{callee();}, flag);
Вы можете использовать это:
void caller()
{
static class Once { public: Once(){callee();}} Once_;
}
Скрыть функцию можно с помощью указателя функции.
static void real_function()
{
//do stuff
function = noop_function;
}
static void noop_function()
{
}
int (*function)(void) = real_function;
Звонящие просто вызывают function
, который будет выполнять работу в первый раз, и ничего не делать при последующих вызовах.
Ваш первый вариант с булевым флагом bFirst
- это не что иное, как экспликация в ручном исполнении того, что компилятор сделает для вас в ваших других вариантах.
Другими словами, в типичной реализации во всех вариантах, которые вы представляли до сих пор, будет дополнительная проверка для булевого флага в сгенерированном машинного кода. Активация всех этих вариантов будет одинаковой (если это ваша забота). Дополнительный код в первом варианте может выглядеть менее изящным, но для меня это не очень важно. (Оберните его.)
В любом случае, то, что у вас есть в качестве первого варианта, в основном, как это обычно делается (пока вы не начнете разбираться с такими проблемами, как многопоточность и т.д.).
Вдохновленный некоторыми людьми, я думаю, что просто использовать макрос, чтобы обернуть выражение запятой, также будет ясно:
#define CALL_ONCE(func) do {static bool dummy = (func, true);} while(0)