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

Как выполнить часть кода только один раз?

У меня есть приложение, в котором есть несколько функций. Каждая функция может быть вызвана много раз на основе пользовательского ввода. Однако мне нужно выполнить небольшой сегмент кода внутри функции только один раз, сначала при запуске приложения. Когда эта же функция снова вызывается в более поздний момент времени, этот конкретный фрагмент кода не должен выполняться. Код находится в VС++. Скажите, пожалуйста, самый эффективный способ справиться с этим.

4b9b3361

Ответ 1

Использовать глобальные статические объекты с конструкторами (которые вызываются до main)? Или просто внутри обычной

static bool initialized;
if (!initialized) {
   initialized = true;
   // do the initialization part
}

Очень мало случаев, когда это не достаточно быстро!


добавлений

В многопоточном контексте этого может быть недостаточно:

Вы также можете быть заинтересованы в pthread_once или constructor функция __attribute__ GCC.

С С++ 11 вам может понадобиться std:: call_once.

Вы можете использовать <atomic> и, возможно, объявить static volatile std::atomic_bool initialized; (но вам нужно быть осторожным), если ваша функция может быть вызывается из нескольких потоков.

Но они могут быть недоступны в вашей системе; они доступны в Linux!

Ответ 2

Использование С++ 11 - используйте std::call_once

#include <mutex>

std::once_flag onceFlag;

{
    ....
    std::call_once ( onceFlag, [ ]{ /* my code body here runs only once */ } );
    ....
}

Ответ 3

Вы можете использовать локальную статическую переменную:

void foo()
{
     static bool wasExecuted = false;
     if (wasExecuted)
         return;
     wasExecuted = true;

     ...
}

Ответ 4

Компактная версия с использованием лямбда-функции:

void foo()
{
    static bool once = [](){
        cout << "once" << endl;
        return true;
    } ();
    cout << "foo" << endl;
}

Код в лямбда-функции выполняется только один раз, когда статическая переменная инициализируется возвращаемым значением лямбда-функции. Он должен быть потокобезопасным, если ваш компилятор поддерживает поточную статическую инициализацию.

Ответ 5

Вы могли бы сделать это

имеют функцию, которая возвращает bool или некоторый тип данных, называемый init

Я сделал так, что вам нужно статическое bool, чтобы это произошло.

bool init()
{
  cout << "Once " <<endl;
  return true||false;// value isn't matter
}

void functionCall()
{
    static bool somebool = init(); // this line get executed once
    cout << "process " <<endl;
}

int main(int argc, char *argv[])
{
    functionCall();
    functionCall();
    functionCall();

    return EXIT_SUCCESS;
}

Ответ 6

Кроме ответа @Basile, вы можете использовать lambda для инкапсуляции статической переменной следующим образом:

if ([] {
    static bool is_first_time = true;
    auto was_first_time = is_first_time;
    is_first_time = false;
    return was_first_time; } ()) 
{ 
    // do the initialization part
}

Это упрощает преобразование в макрос общего назначения:

#define FIRST_TIME_HERE ([] { \
    static bool is_first_time = true; \
    auto was_first_time = is_first_time; \
    is_first_time = false; \
    return was_first_time; } ())

Что можно разместить в любом месте, которое вы хотите по запросу:

if (FIRST_TIME_HERE) {
    // do the initialization part
}

И для хорошей меры atomics укоротить выражение и сделать его потокобезопасным:

#include <atomic>
#define FIRST_TIME_HERE ([] { \
    static std::atomic<bool> first_time(true); \
    return first_time.exchange(false); } ())