C++ 如何只执行一段代码一次?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8412630/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 18:31:47  来源:igfitidea点击:

How to execute a piece of code only once?

c++staticglobal-variables

提问by Darzen

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.

我有一个应用程序,其中有几个功能。每个函数都可以根据用户输入多次调用。但是,我只需要在一个函数中执行一小段代码,最初是在应用程序启动时。当稍后再次调用相同的函数时,不得执行这段特定的代码。代码在VC++ 中。请告诉我处理这个问题的最有效方法。

回答by Bediver

Compact version using lambda function:

使用 lambda 函数的紧凑版本:

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.

当静态变量被初始化为 lambda 函数的返回值时,lambda 函数中的代码只执行一次。只要您的编译器支持线程安全的静态初始化,它就应该是线程安全的。

回答by Soren

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

使用 C++11——使用 std::call_once

#include <mutex>

std::once_flag onceFlag;

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

回答by Basile Starynkevitch

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

将全局静态对象与构造函数(之前调用过main)一起使用?或者只是在例行程序中

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_onceor constructorfunction __attribute__of GCC.

您可能还对pthread_onceGCC 的constructor函数__attribute__感兴趣。

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

使用 C++11,您可能需要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.

如果您的函数可以从多个线程调用,您可能想要使用<atomic>并可能声明static volatile std::atomic_bool initialized;(但您需要小心)。

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

但是这些可能在您的系统上不可用;它们在 Linux 上可用!

回答by Abyx

You can use local static variable:

您可以使用局部静态变量:

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

     ...
}

回答by aah134

could you do this

你能这样做吗

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

有一个返回 bool 或某种名为 init 的数据类型的函数

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

我是这样实现的,你需要 static 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;
}

for C

对于 C

#include <stdio.h>

void init()
{
    printf("init\n");
}

void process()
{
    static int someint = 0;
    if(someint == 0)
    {
        someint = 1;
        init();
    }
    printf("process\n");
}


int main()
{
    process();
    process();
    process();
    return 0;
}

回答by John McFarlane

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

除了@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
}

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

回答by underscore_d

As of C++11, static local variables are thread-safe and usually sufficient for most cases, so std::call_once()et al.very well may be overkill.

从 C++11 开始,静态局部变量是线程安全的,通常对于大多数情况来说已经足够了,所以std::call_once()等人。很好可能是矫枉过正。

This looks especially elegant when using C++17's initialisation-within-ifand std::exchange():

当使用 C++17 的内部初始化if和和时,这看起来特别优雅std::exchange()

#include <utility>

void
do_something_expensive_once()
{
    if ( static auto called = false; !std::exchange(called, true) ) {
        do_something_expensive();
    }
}

If this is a pattern you use a lot, then we can encapsulate it via a tag type:

如果这是一个你经常使用的模式,那么我们可以通过一个标签类型来封装它:

template <typename T>
auto
call_once()
{
    static auto called = false;
    return !std::exchange(called, true);
}

void
do_something_expensive_once()
{
    struct TagForSomethingExpensive final {};

    if ( call_once<TagForSomethingExpensive>() ) {
        do_something_expensive();
    }
}

Alternatively, you could template on a function's address, a unique integer, etc.

或者,您可以对函数的地址、唯一整数等进行模板化。

You can then also pass a callable to call_once(), and so on, and so forth. As usual for C++: the possibilities are endless!

然后,您还可以将可调用对象传递给call_once(),依此类推。和 C++ 一样:可能性是无限的!