您的位置:首页 > 编程语言 > C语言/C++

C++ 内存布局:内存布局基础

2016-06-24 00:13 435 查看
1、在C++中,内存分成5个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。

栈:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

堆:就是那些由new分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。

自由存储区:就是那些由malloc等分配的内存块,他和堆是十分相似的,不过它是用free来结束自己的生命的。

全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的C语言中,全局变量又分为初始化的和未初始化的,在C++里面没有这个区分了,他们共同占用同一块内存区。

常量存储区:这是一块比较特殊的存储区,他们里面存放的是常量,不允许修改。

2、C++中考虑内存布局,主要是针对类内部的内存分布。类的内存分布涉及的内容比较多,我们先从最简单的来看。

一、一个简单的类,没有继承,没有虚函数表

#include <iostream>
using namespace std;

class CBase
{
//public
public:
CBase()
{

}
};

class CBaseClass
{
//private members
private:
int nCount;

//public members
public:

//private member funcs
private:
CBaseClass(const CBaseClass &base)
{

}

CBaseClass &operator = (const CBaseClass& base)
{
return *this;
}

//public members
public:
CBaseClass(int count = 0)
{
nCount = count;
}
~CBaseClass()
{

}
};

void main()
{
CBase base;
cout << "base Size" << sizeof(base) << endl;

CBaseClass baseClass(10);
cout << "baseClass Size" << sizeof(baseClass) << endl;

cin.get();

}
上面代码的输出如下所示:



第一个CBase 的大小是1,虽然CBase只有一个构造函数,但是这个1并不是构造函数所占据的内存空间。构造函数所占据的内存空间在全局区。使用sizeof(CBase)所得到的大小,是编译器优化的结果。
第二个CBaseClass 的大小是4,这是因为CBaseClass 的内部含有一个int型的变量,该变量占据4字节,所以输出的值便是4字节。CBaseClass中那么多的函数,不论是public还是private,均处于全局区。



上面这幅图是在VS2013 X86(Win32 Debug)的条件下进行编译的,得到上面的内存布局图,我们可以清除的看到每个类中的成员分布。

二、简单的继承
在上面的代码的基础上进行扩展,得到如下的代码
#include <iostream>
using namespace std;

class CBase
{
//public
public:
CBase()
{

}
};

class CBaseClass
{
//private members
private:
int nCount;

//public members
public:

//private member funcs
private:
CBaseClass(const CBaseClass &base)
{

}

CBaseClass &operator = (const CBaseClass& base)
{
return *this;
}

//public members
public:
CBaseClass(int count = 0)
{
nCount = count;
}
~CBaseClass()
{

}
};

class CDerivedClass : public CBaseClass
{
//private members:
private:
int nDeriveCount;

//public members
public:
int nCurrentNum;

//private member funcs
private:
CDerivedClass(const CDerivedClass& derived)
{

}

CDerivedClass & operator = (const CDerivedClass &derived)
{
return *this;
}
//public member funcs
public:
CDerivedClass(int nDerived = 0)
{
nDeriveCount = nDerived;
nCurrentNum = 0;
}

};

void main()
{
CBase base;
cout << "base Size:" << sizeof(base) << endl;

CBaseClass baseClass(10);
cout << "baseClass Size:" << sizeof(baseClass) << endl;

CDerivedClass derivedClass(12);
cout << "derivedClass Size:" << sizeof(derivedClass) << endl;

cin.get();

}


代码输出的内容如下:



我们可以看到baseClass 的大小任然是4,这也在一定的层次上说明了继承不会影响基类的内存分布。derivedClass 大小是12,这是因为除了其本身的两个int型的成员变量外,还有基类的成员变量。虽然基类的成员变量是私有的,derivedClass对这一私有成员没有访问权限,但是从继承体系上来看,派生类继承了基类的所有的内部关系,所以在计算派生类的大小时,需要考虑基类的大小。



上图展示出了基类和派生类的内存分布关系

三、多继承
继续修改上面的代码,得到如下的内容
#include <iostream>
using namespace std;

class CBase
{
//public
public:
CBase()
{

}
};

class CBaseClass
{
//private members
private:
int nCount;

//public members
public:

//private member funcs
private:
CBaseClass(const CBaseClass &base)
{

}

CBaseClass &operator = (const CBaseClass& base)
{
return *this;
}

//public members
public:
CBaseClass(int count = 0)
{
nCount = count;
}
~CBaseClass()
{

}
};

class CBaseClassNew
{
//private members
private:
int nCount;

//public members
public:
int nNewCount;
//private member funcs
private:
CBaseClassNew(const CBaseClassNew &base)
{

}

CBaseClassNew &operator = (const CBaseClassNew& base)
{
return *this;
}

//public members
public:
CBaseClassNew(int count = 0)
{
nCount = count;
}
~CBaseClassNew()
{

}
};

class CDerivedClass : public CBaseClass
{
//private members:
private:
int nDeriveCount;

//public members
public:
int nCurrentNum;

//private member funcs
private:
CDerivedClass(const CDerivedClass& derived)
{

}

CDerivedClass & operator = (const CDerivedClass &derived)
{
return *this;
}
//public member funcs
public:
CDerivedClass(int nDerived = 0)
{
nDeriveCount = nDerived;
nCurrentNum = 0;
}

};

class CMultiDerivedClass :public CDerivedClass, public CBaseClassNew
{
//private members
private:
int nMultiCount;

//public members
public:
int nNewMultiCount;

//private member funcs
private:
CMultiDerivedClass(const CMultiDerivedClass& derived)
{

}

CMultiDerivedClass & operator = (const CMultiDerivedClass &derived)
{
return *this;
}
//public member funcs
public:
CMultiDerivedClass(int nCount)
{
nMultiCount = nCount;
nNewMultiCount = 0;
}

~CMultiDerivedClass()
{

}

};

void main()
{
CBase base;
cout << "base Size:" << sizeof(base) << endl;

CBaseClass baseClass(10);
cout << "baseClass Size:" << sizeof(baseClass) << endl;

CDerivedClass derivedClass(12);
cout << "derivedClass Size:" << sizeof(derivedClass) << endl;

CMultiDerivedClass multiDerivedClass(5);
cout << "multiDerivedClass Size:" << sizeof(multiDerivedClass) << endl;

cin.get();

}


上面代码的输出如下:



其内存分布如下图所示:



从其内存分布来看,可以很明了的知道多继承CMultiDerivedClass的大小为28,因为上面有7个变量。多继承具体的关系如下图所示:



多继承内存分布总是从第一个继承的类的成员开始分布,然后是第二个,第三个....

在考虑类的内存布局时,同样需要考虑内存对齐等问题。这一方面,在这不多说,网上的资料很多。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: