0.从今天开始收集看过的优秀或常用的代码片,希望自己的代码也能出现在这边。
1.绝不简单的判断素数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
解析: 素数只有1,本数字是自己的约数。首先把大于2的偶数排除在外,一半的几率让直接否定为素数,充分利用素数的特点。然后是i<n/2,因为显然素数不会被大于n/2的给整除;i+=2,因为显然素数不会整除大于2的偶数;
2.单例模式的线程安全版
class Lock
{
private:
CCriticalSection m_cs;
public:
Lock(CCriticalSection cs) : m_cs(cs)
{
m_cs.Lock();
}
~Lock()
{
m_cs.Unlock();
}
};
class Singleton
{
private:
Singleton();
Singleton(const Singleton &);
Singleton& operator = (const Singleton &);
public:
static Singleton *Instantialize();
static Singleton *pInstance;
static CCriticalSection cs;
};
Singleton* Singleton::pInstance = 0;
Singleton* Singleton::Instantialize()
{
if(pInstance == NULL)
{ //double check
Lock lock(cs); //用lock实现线程安全,用资源管理类,实现异常安全
//使用资源管理类,在抛出异常的时候,资源管理类对象会被析构,析构总是发生的无论是因为异常抛出还是语句块结束。
if(pInstance == NULL)
{
pInstance = new Singleton();
}
}
return pInstance;
}
解析:2次判断pInstance == NULL是因为pInstance == NULL 大部分情况下都为false,这样只在第一次调用Instantialize()的时候才加锁,可大大提高效率。另外需要指出的是,pInstance可以是指向该类的父类,甚至子类的指针类型。
3.do ...while(0) 可以避免代码冗余
bool Execute()
{
// 分配资源
int *p = new int;
bool bOk(true);
do
{
// 执行并进行错误处理
bOk = func1();
if(!bOk) break;
bOk = func2();
if(!bOk) break;
bOk = func3();
if(!bOk) break;
// ..........
}while(0);
// 释放资源
delete p;
p = NULL;
return bOk;
}
重复利用了// 释放资源 的那个三句代码。在网络编程中随便一个send,recv等函数操作都需要检查成功与否,或许也能用上哦。 还有,最明显的是,cocos2d-x里的很多init函数,如helloworldScene里的init()函数,就用到了do while(0),因为里面创建很多对象,每个对象创建完就用BB_BREAK_IF(pObj)判断,如果外面没有do while(0),是不能出现break;跳出循环语句的。嘿嘿。
4.常用的宏定义
#define max(a,b) (((a) > (b)) ? (a) : (b))
#define min(a,b) (((a) < (b)) ? (a) : (b))
#define SAFE_DELETE(p) {if(p){delete p;p=NULL;}}
#define CC_SAFE_DELETE(p) do { if(p) { delete (p); (p) = 0; } } while(0)
#define CC_SAFE_DELETE_ARRAY(p) do { if(p) { delete[] (p); (p) = 0; } } while(0)
#define CC_SAFE_FREE(p) do { if(p) { free(p); (p) = 0; } } while(0)
#define CC_SAFE_RELEASE(p) do { if(p) { (p)->release(); } } while(0)
#define CC_SAFE_RELEASE_NULL(p) do { if(p) { (p)->release(); (p) = 0; } } while(0)
#define CC_SAFE_RETAIN(p) do { if(p) { (p)->retain(); } } while(0)
#define CC_BREAK_IF(cond) if(cond) break
#if !defined(COCOS2D_DEBUG) || COCOS2D_DEBUG == 0
#define CHECK_GL_ERROR_DEBUG()
#else
#define CHECK_GL_ERROR_DEBUG() \
do { \
GLenum __error = glGetError(); \
if(__error) { \
CCLog("OpenGL error 0x%04X in %s %s %d\n", __error, __FILE__, __FUNCTION__, __LINE__); \
} \
} while (false)
#endif
/**
* define a create function for a specific type, such as CCLayer
* @__TYPE__ class type to add create(), such as CCLayer
*/
#define CREATE_FUNC(__TYPE__) \
static __TYPE__* create() \
{ \
__TYPE__ *pRet = new __TYPE__(); \
if (pRet && pRet->init()) \
{ \
pRet->autorelease(); \
return pRet; \
} \
else \
{ \
delete pRet; \
pRet = NULL; \
return NULL; \
} \
}
解析:往往用于需要启用预编译头的头文件,整个项目通用的头文件。就像as3.0里常常写的utils包里的类。另外,do while(0)的使用常常出现于库,引擎中的宏定义,其用法的解释看http://www.cnblogs.com/flying_bat/archive/2008/01/18/1044693.html
好棒的调试方法。
5.枚举类型和数组的完美搭配使用,摘自cocos2d-x的源码
enum
{
TEST_ACTIONS = 0,
TEST_TRANSITIONS,
TEST_PROGRESS_ACTIONS,
TEST_EFFECTS,
TEST_CLICK_AND_MOVE,
TESTS_COUNT
};
const std::string g_aTestNames[TESTS_COUNT] = {
"ActionsTest",
"TransitionsTest",
"ActionsProgressTest",
"EffectsTest",
"ClickAndMoveTest",
};
解析:这招好啊,利用枚举类型的特性编译时自动取得了TESTS_COUNT的值。用于下面的需要编译时即要知道大小数组,可拓展性强。即便不和数组搭配,枚举的最后一个COUNT也常用于其他地方。
6.和自己的同类对象指针比较
bool CCObject::isEqual(const CCObject *pObject)
{
return this == pObject;
}
解析: 实现这个函数挺新鲜的,假如一个层里有多个CCObject,在当前CCobject遍历这个层里的多个CCObject是有时需要判断一下,排除自己。例如:群聚时计算别的对象的平均位置,当然要除了自己。