#include <iostream>
using namespace std;
class A{
public:
void ptf(void)
{
cout << "test" << endl;
}
static A& GetInstance(void)
{
return m_a;
}
private:
A(void){};
A(const A&){};
static A m_a;
}
A A::m_a;
int main(void)
{
A& a = A::GetInstance();
a.ptf();
cout << "sizeof(A) = " << sizeof(A) << " and sizeof(a) = " << sizeof(a) << endl;//sizeof(A) = 1 and sizeof(a) = 1
getchar();
return 0;
}
由于A中的成员m_a是静态的,属于类,且具有进程级的声明周期,在构造A对象时,不用管m_a,所以可以构造出A对象。
但是由于其具有进程级的声明周期,在进程启动时,就会分配A对象的内存,如果A成员变量占用较多内存,则会一直占用较多内存。
此类中除了A::m_a没有其他成员。所以sizeof(A) = 1;sizeof(a) = 1;
优化方式是:
一种是使用指针类型的A* A::m_pa;但此种方式依然至少占用一个sizeof(A*)大小内存,即全局区内存占用只多了一个指针所占内存大小。
另外也可以这样定义:
static A* A::GetInstance2(void)
{
static A a;
return &a;
}
使用这种方式会在首次调用的时候分配空间。
至于是使用
static A* A::GetInstance2(void)
{
static A a;
return &a;
}
还是
static A* A::GetInstance2(void)
{
static A* pa = NULL;
if(NULL == pa)
{
pa = new A;
}
return pa;
}
有差异,懒汉和恶汉模式,一个使用时初始化,一个是启动就初始化了。另外就是一个在栈一个在堆。
至于上面sizeof(A)占用内存为1个字节
参看:C/C++—— C++中一个空对象为什么还要占用一个字节空间
摘要如下:
1.标准对此的确有规定,但没有明确规定空对象一定要是1字节,标准只是规定了对象的大小必须大于0,首先标准中有如下标定“An object is a region of storage. ”。
2.显然不存在0字节长度的存储区域,这句话隐含了空对象是大于0的,另外还有标定“a most derived object shall have a non-zero size and shall occupy one or more bytes of storage. Base class sub-objects may have zero size. An object of POD contiguous bytes of storage.”,
说明了最终派生对象大小是非0值,其大小可以是1或多个字节,基类子对象可以为0(任何可直接创建的对象都不会为0,如果一个类A是个空类,那么直接创建对象的时候大小为1,如果B类从A类派生并且没有额外的数据成员,那么直接创建B类时大小依然为1,规定对基类子对象可为0的规定使的编译器会进行空基类优化)。
3.最后在关于sizeof操作符中也有相关规定“The size of a most derived class shall be greater than zero ”,可见规定的确规定了空对象大小不能为0的现实,但却不强制其大小一定为1(这为编译器为不同的操作系统进行优化留有余地,比如说在不同字长[8,16,32,64]位CPU下,最有效率的操作数类型都是CPU的字长,那么编译器可以选择机器字长来作为不为0时的最小长度)。