How to execute a piece of code only once?

2019-01-14 12:27发布

I have an application which has several functions in it. Each function can be called many times based on user input. However I need to execute a small segment of the code within a function only once, initially when the application is launched. When this same function is called again at a later point of time, this particular piece of code must not be executed. The code is in VC++. Please tell me the most efficient way of handling this.

6条回答
我想做一个坏孩纸
2楼-- · 2019-01-14 13:03

You can use local static variable:

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

     ...
}
查看更多
Summer. ? 凉城
3楼-- · 2019-01-14 13:13

Compact version using lambda function:

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

Code within lambda function is executed only once, when the static variable is initialized to the return value of lambda function. It should be thread-safe as long as your compiler support thread-safe static initialization.

查看更多
你好瞎i
4楼-- · 2019-01-14 13:15

Additionally to @Basile's answer, you can use a lambda to encapsulate the static variable as follows:

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
}

This makes it easy to convert into a general-purpose macro:

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

Which can be placed anywhere you want call-by-need:

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

And for good measure, atomics shorten the expression and make it thread-safe:

#include <atomic>
#define FIRST_TIME_HERE ([] { \
    static std::atomic<bool> first_time(true); \
    return first_time.exchange(false); } ())
查看更多
聊天终结者
5楼-- · 2019-01-14 13:18

Use global static objects with constructors (which are called before main)? Or just inside a routine

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

There are very few cases when this is not fast enough!


addenda

In multithreaded context this might not be enough:

You may also be interested in pthread_once or constructor function __attribute__ of GCC.

With C++11, you may want std::call_once.

You may want to use <atomic> and perhaps declare static volatile std::atomic_bool initialized; (but you need to be careful) if your function can be called from several threads.

But these might not be available on your system; they are available on Linux!

查看更多
可以哭但决不认输i
6楼-- · 2019-01-14 13:18

could you do this

have a function that return a bool or some datatype called init

I made it happen this way, you need static bool to make it happens

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;
}
查看更多
等我变得足够好
7楼-- · 2019-01-14 13:26

Using C++11 -- use the std::call_once

#include <mutex>

std::once_flag onceFlag;

{
    ....
    std::call_once ( onceFlag, [ ]{ /* my code body here runs only once */ } );
    ....
}
查看更多
登录 后发表回答