看到一段ogre的原码看到在sigleton.h中的
int offset = (int)(t*)1 - (int)(singleton <t>*)(t*)1;这段看不明白请各位高手指点8,9。
下面是原码:
namespace ogre {
template <typename t> class singleton
{
protected:
static t* ms_singleton;
public:
singleton( void )
{
assert( !ms_singleton );
int offset = (int)(t*)1 - (int)(singleton <t>*)(t*)1;
ms_singleton = (t*)((int)this + offset);
}
~singleton( void )
{ assert( ms_singleton ); ms_singleton = 0; }
static t& getsingleton( void )
{ assert( ms_singleton ); return ( *ms_singleton ); }
static t* getsingletonptr( void )
{ return ms_singleton; }
};
}
谢谢请各位详细说明一下。
在静态变量 ms_singleton保存当前singleton<t>类对象的首地址。比如
singleton<double> d;
则&d==singleton<double>::ms_singleton
int offset = (int)(t*)1 - (int)(singleton <t>*)(t*)1;这句话其实是防止编译器在将t*转换为(singleton <t>*)指针的时候产生偏移,所以在将ms_singleton转换为(singleton <t>*)的时候也能正常使用。
指针在做类型转换的时候可能会发生偏移,比如以下代码:
class cbase{
public:
int m_i;
};
class ca:public cbase
{
public:
virtual ~ca(){};
};
int main()
{
ca a;
ca*p=&a;
cbase *pbase=p;//pbase的值发生了偏移
return 0;
}
这代码写的...;(
估计它的用法是
singleton<s>* ss = reinterpret_cast<singleton<s>*>(new s);
new(ss) singleton<s>;
如果用法真是这样这玩意也实在是太畸形了。
那段怪异的代码的作用肯定是防止意外偏移,不过第一,这种特定情况下不见得会有偏移,第二,它的做法也决不是符合标准的。
class ca :public singleton<ca>
{
int a;
};
ca * singleton<ca>::ms_singleton;
int main(int argc, char* argv[])
{
char *preceipt = "ff";
ca obj;
cout << sizeof(obj) << endl;
return 0;
}
因为基类为空,当空基类优化时基类将不在ca中占空间.不管是否优化singleton<ca>::ms_singleton都将指向ca的唯一对象;
int offset = (int)(t*)1 - (int)(singleton <t>*)(t*)1;就是用来计算偏移的,如果ca有虚函数,你看看这个offset还是不是0?变成-4了.