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
How to execute a piece of code only once?
提问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 constructor
function __attribute__
of GCC.
您可能还对pthread_once或GCC 的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-if
and 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++ 一样:可能性是无限的!