如何保证某个函数只被调用一次

 

一个函数caller会在其内部调用另外一个函数callee,现在的情况是,caller可能会在多个地方被多次调用,而你希望callee只在第一次被调用时被调用一次。一般情况下,callee会是一个对环境或者资源的初始化工作。

或许,从代码结构的角度来讲,你第一个想到的是把callee从caller中拿出来,放到某个合适的地方做初始化,这是个不错的方法,但相信我,在有些时候这并不是个有效的办法:你可能无法找个那个“合适的地方”,你也可能找到了但因此而失去lazy initialization的好处~~~。

这里,我只想对这个问题找个好点的方法。

第一个方法很简单,就是用个静态的flag来判断:


static bool flag = false; if(!flag) {     callee();     flag = true; }

这个可以非常完美的工作,但是代码感觉多了点,不够简洁。

而且每个后续调用都要有个取反和判断操作,这对调用频繁的操作的性能是有影响的。另外,即使影响不大,从程序员感受的角度来看,你也不希望有多余的判断~~~

哦,取反可以去掉:


static bool flag = true; if(flag) {     callee();     flag = false; }

但是,判断还是存在。

【编辑:SO上讨论中有人指出,即使使用static变量,其实也会有一个判断操作,这一点说出了问题的根本,所以关于效率的论述是不必要的】

当然,我们还有第二种更简洁的方法,假设callee的返回类型时int:

static int dummy = callee(); // 1)

完了,利用静态变量只初始化一次的特点就可以实现,简洁,而且高效。

但是,这里有个问题:如果callee的返回类型时void,那怎么办?你不能:

static void dummy = callee(); static int dummy = (int)callee(); static int dummy = reinterpret_cast<int>(callee());

因为void其实不是个类型,而是没有类型。

即使你觉得自己很聪明,想出了下面这种方式:

bool dummyfunc(void){return true;} static bool dummy = dummyfunc(callee());

那也是不灵光的,不要以为callee返回void,把返回的void传给dummyfunc的参数就可以了,因为void根本就不是个类型,根本没有赋值,传值这个概念~~~

幸亏C++中还有个叫逗号表达式的东西,说实话,C++用了7年多,这是我第一次发现逗号表达式这么可爱:

逗号表达式会这个计算每个子表达式,并返回最后一个子表达式的值

于是,就有了这个解决方案:

static bool dummy = (callee(), true); // 2)

也是同样的简洁、高效。

看来,直接用静态变量初始化的方法是可以达到这个目的,而且会更好。

附:

我相信还会有其他方法来处理callee返回void的情况的,如果你知道,请不吝赐教!

来源:http://www.cnblogs.com/baiyanhuang/archive/2010/11/13/1876677.html

VC++函数只被调用一次的更多相关文章

  1. vc MFC 通过IDispatch调用默认成员函数

    CComPtr<IDispatch> spDisp(IDispatch *); if(!spDisp) return; DISPPARAMS dispParam={0}; //没有参数 V ...

  2. VS2013 VC++的.cpp文件调用CUDA的.cu文件中的函数

    CUDA 8.0在函数的调用中方便的让人感动.以下是从网上学到的VC++的.cpp文件调用CUDA的.cu文件中的函数方法,和一般的VC++函数调用的方法基本没差别. 使用的CUDA版本为CUDA 8 ...

  3. VC++线程函数内怎么调用外部函数

    VC++线程函数内怎么调用外部函数 1.把外部函数做成静态函数,就可以直接调用了.2.把外部函数所在的对象通过线程函数参数传到线程里面来,这样线程里可以使用此对象及其函数了.

  4. [Effective JavaScript 笔记]第17条:间接调用eval函数优于直接调用

    eval函数不仅仅是一个函数.大多数函数只访问定义它们所在的作用域,而不能访问除此之外的作用域(词法作用域).eval函数具有访问调用它时的整个作用域的能力.编译器编写者首次设法优化js时,eval函 ...

  5. JavaScript函数的各种调用模式

    函数是JavaScript世界里的第一公民,换句话来说,就是我们如果可以精通JavaScript函数的使用,那么对JavaScript的运用可以更游刃有余了.熟悉JavaScript的人应该都知道,同 ...

  6. python中函数的定义,调用,全局变量,局部变量,函数的嵌套使用-初级篇

    函数的基本概述 在学习函数之前,一直遵循:面向过程编程,即:根据业务逻辑从上到下实现功能,可以思考一下如果有某个功能的代码是在多个地方使用的是否可以只写一次?此时的代码该如何定义.先观察以下的案例: ...

  7. linux中 probe函数的何时调用的?

    点击打开链接 linux中 probe函数何时调用的 所以的驱动教程上都说:只有设备和驱动的名字匹配,BUS就会调用驱动的probe函数,但是有时我们要看看probe函数里面到底做了什么,还有传递给p ...

  8. ES6躬行记(15)——箭头函数和尾调用优化

    一.箭头函数 箭头函数(Arrow Function)是ES6提供的一个很实用的新功能,与普通函数相比,不但在语法上更为简洁,而且在使用时也有更多注意点,下面列出了其中的三点: (1)由于不能作为构造 ...

  9. day11函数的参数,函数对象 - 函数名,函数的嵌套调用

    复习 # 什么是函数:具体特定功能的代码块 - 特定功能代码块作为一个整体,并给该整体命名,就是函数 # 函数的优点: # 1.减少代码的冗余 # 2.结构清晰,可读性强 # 3.具有复用性,开发效率 ...

随机推荐

  1. [Spring] Bean Scope Singleton cs Prototype

    We can define a class to be Singleton or Prototype. If the class was defined as Prototype, then ever ...

  2. js算法:分治法-循环赛事日程表

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...

  3. 再探gdb经常使用命令

     前面已经有了一篇对gdb经常使用命令的总结.见 http://blog.csdn.net/u011848617/article/details/12838875 这里对眼下学过的gdb命令进行了 ...

  4. Eclipse 常用快捷键及使用技巧

    做 java 开发的,经常会用 Eclipse 或者 MyEclise 集成开发环境,一些实用的 Eclipse 快捷键和使用技巧,可以在平常开发中节约出很多时间提高工作效率,下面我就结合自己开发中的 ...

  5. jeasyUI treegrid 的 reload 和 getChanges

    看上去,treegrid继承自datagrid,因此,datagrid有的,treegrid也会有. 比如说,getChanges,翻看那些网络教程,绝大多数都没提treegrid有这个东东.但是,t ...

  6. location.replace

    [root@bigdata-server-01 ~]# curl www.baidu.com<!DOCTYPE html><!--STATUS OK--><html> ...

  7. ubuntu tftp【转】

    本文转载自:http://www.cnblogs.com/wxl309729255/articles/2816594.html 配置eth0的 IP地址, 同时激活该设备. #ifconfig eth ...

  8. 13.Ext.extend用法以及代码解读

    转自:http://www.blogjava.net/dragonshrimp/archive/2008/03/01/183060.html Ext.extend用法以及代码解读 概述 Ext.ext ...

  9. MySQL 备份和恢复数据

    备份指定数据库的全部表或指定表 mysqldump -u user -h localhost -p [password] db_name[ tbl_name[,tbl_name.......]]> ...

  10. bzoj 1572: [Usaco2009 Open]工作安排Job【贪心+堆】

    先按照时间顺序加,价值塞进小根堆里,碰到不合法情况就从堆里减去 #include<iostream> #include<cstdio> #include<queue> ...