函数调用防护
假设我有一个名为 InitFoo
的免费函数。 我想保护这个函数不被意外多次调用。 我没有多想就写下了以下内容:
void InitFoo()
{
{
static bool flag = false;
if(flag) return;
flag = true;
}
//Actual code goes here.
}
不过,这看起来像一个大疣。 InitFoo
不需要保留任何其他状态信息。 有人可以建议一种方法来实现相同的目标而不丑陋吗?
当然,宏不算数。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
您还需要它是多线程安全的吗? 研究带有双重检查锁定的单例模式(这很容易出错)。
如果您不想为此使用整个类,另一种简单的方法是:
在 .cpp 中(不要在 .h 中声明 InitBlah)
没有人可以在此 .cpp 之外调用它,并且它会被调用。 当然,有人可以在这个 .cpp 中调用它——取决于你对它不可能、不方便和有记录的关心程度。
如果您关心顺序或在特定时间执行操作,那么 Singleton 可能适合您。
Do you also need it to be multi-thread safe? Look into the Singleton pattern with double-check locking (which is surprising easy to get wrong).
If you don't want a whole class for this, another simple way is:
In a .cpp (don't declare InitBlah in the .h)
No one can call it outside of this .cpp, and it gets called. Sure, someone could call it in this .cpp -- depends on how much you care that it's impossible vs. inconvenient and documented.
If you care about order or doing it at a specific time, then Singleton is probably for you.
我就是这么做的。 如果您想要替代方案,您可以使用一些函数指针改组:
That is exactly how I'd do it. You could use some function pointer shuffling if you want an alternative:
好吧,构造函数只会自动调用一次。 如果您创建此类的单个实例:
那么
//do stuff
将仅执行一次。 执行两次的唯一方法是创建该类的另一个实例。您可以通过使用 Singleton 来防止这种情况。 实际上,
//do stuff
只能被调用一次。Well, a constructor is only automatically called once. If you create a single instance of this class:
Then
//do stuff
will only execute once. The only way to execute it twice is to create another instance of the class.You can prevent this by using a Singleton. In effect,
//do stuff
can only possibly be called once.对我来说,这听起来像是一个只会在调试过程中出现的问题。 如果是这样的话,我会简单地执行以下操作:
这个特定的疣的目的很容易通过查看它来辨别,并且如果程序员错误地调用 < code>InitFoo 多次。 它也将在生产代码中完全消失。 (当定义
NDEBUG
时)。编辑:关于动机的快速说明:
多次调用 init 函数可能是一个很大的错误。 如果此函数的最终用户错误地调用了它两次,那么静静地忽略该错误可能不是正确的方法。 如果您不采用
assert()
路线,我建议至少将消息转储到stdout
或stderr
。To me, this sounds like an issue that will only come up during debugging. If that is the case, I would simply do the following:
The purpose of this particular wart is easily discerned just by looking at it, and it will cause a nice, big, flashy assertion failure if a programmer ever makes the mistake of calling
InitFoo
more than once. It will also completely dissapear in production code. (whenNDEBUG
is defined).edit: A quick note on motivation:
Calling an init function more than once is probably a big error. If the end user of this function has mistakenly called it twice, quietly ignoring that mistake is probably not the way to go. If you do not go the
assert()
route, I would recommend at least dumping a message out tostdout
orstderr
.您可以通过一些不同的丑陋来做到这一点:
您仍在使用
static
,但现在您不需要进行自己的标志检查 -static
已经放入了一个标志并对其进行检查,因此它仅构造i
一次。You can do it with some different ugliness:
You're still using
static
, but now you don't need to do your own flag checking -static
already puts in a flag and a check for it, so it only constructsi
once.在需要一次性但不值得整堂课的情况下,我总是这样做。 当然,它假设您不担心与线程相关的问题。 我通常在变量名前加上“s_”前缀,以明确它是一个静态变量。
I do exactly that all the time with situations that need that one-time-only-but-not-worth-making-a-whole-class-for. Of course, it assumes you don't worry about thread-related issues. I usually prefix the variable name with "s_" to make it clear that it's a static variable.
嗯...如果您不反对使用Boost,那么请看看boost::call_once:
Hmmm... if you don't object to using Boost, then have a look at boost::call_once:
我并不是对此感到非常兴奋,但这只是另一种方式:函数对象。
Not that I am very excited about it, but this is just another way: function object.