C++内存空间的布局
每个应用都有自己独立的内存空间,其内存空间一般都有:代码段(代码区)、数据段(全局区)、栈空间、堆空间。
代码段(代码区)
用于存放代码。
数据段(全局区)
用于存放全局变量等。
栈空间
每调用一个函数,就会给它分配一段连续的栈空间,等函数调用完后,就会回收空间。
堆空间
在程序运行过程,为了能够自由控制内存的生命周期、大小,会经常使用堆空间的内存。
堆空间的申请和释放
如果内存够用,会分配一块连续的内存空间出来。
malloc和free
void * malloc(size_t size)
void free(void *)
int main()
{
int *p = (int *)malloc(4);
*p = 4;
free(p);
char *chs = (char *)malloc(4);
for ( int i = 0; i < 4; i++ )
*(chs + i) = (char) ('A' + i);
// chs[i] = i + 1;
free(chs);
return 0;
}
new/new[]和delete/delete[]
int main()
{
int *p = new int;
*p = 4;
cout << *p << endl;
delete p;
char *chs = new char[4];
for ( int i = 0; i < 4; i++ )
*(chs + i) = (char) ('A' + i);
// chs[i] = i + 1;
for ( int i = 0; i < 4; i++ )
cout << chs[i] << "\t";
delete[] chs;
return 0;
}
注意
new与free和malloc与delete不可以混着用!!!否则可能会存在内存泄漏。- new出来的数组,必须要用
delete[]释放。
堆空间的初始化
可以使用void * memset(void * dst, int val, size_t n)来初始化。需要#include <cstring>。
dst:目标空间的首地址。
val:要初始化的值。
n:长度,单位是字节。
它的作用是:从dst这个地址开始,将连续的n的字节,每一个字节都设置为val。注意,int占4个字节,所以如果给val写成1的话,二进制应该是00000001 00000001 00000001 00000001,值就是:16843009。

int main()
{
int N = 10;
int size = sizeof(int) * N;
int *p = (int *) malloc(size);
memset(p, 0, size);
for ( int i = 0; i < N; i++ )
cout << p[i] << "\t";
return 0;
}
memset函数是将较大的数据结构(对象、数组等)内存清零的比较快的方法。
class Person
{
public:
int id;
int age;
int height;
};
int main()
{
Person p;
p.id = 1;
p.age = 2;
p.height = 3;
memset(&p, 0, sizeof(p));
Person persons[] = { { 1, 2, 4 }, { 2, 3, 4 }, { 3, 3, 4 } };
memset(&persons, 0, sizeof(persons));
return 0;
}
也可以使用new来初始化。
int main()
{
int *p1 = new int; // 未被初始化,有些平台可能会初始化
int *p2 = new int(); // 被初始化为0
int *p3 = new int(5); // 被初始化为5
int *p4 = new int[3]; // 数组元素未被初始化
int *p5 = new int[3](); // 3个数组元素都被初始化为0
int *p6 = new int[3]{}; // 3个数组元素都被初始化为0
int *p7 = new int[3]{ 5 }; // 数组首元素被初始化为5,其他元素被初
return 0;
}
对象的内存
对象的内存可以存在于3种地方。
-
全局区(数据段):全局变量。
-
栈空间:函数里面的局部变量。
-
堆空间:动态申请内存(
malloc,new等)。class Person { public: int id; int age; int height; }; // 全局区 Person p; int main() { // 栈空间 Person p1; // 堆空间 Person *p2 = new Person; return 0; }
对象成员变量的初始化
默认情况下,成员变量的初始化。
struct Person
{
int id;
};
// 全局区(成员变量初始化为0)
Person p0;
int main()
{
// 栈空间(成员变量不会被初始化)
Person p1;
// 堆空间
Person *p2 = new Person; // 成员变量不会被初始化
Person *p3 = new Person(); // 成员变量初始化为0
Person *p4 = new Person[3]; // 成员变量不会被初始化
Person *p5 = new Person[3](); // 3个Person对象的成员变量都初始化为0
Person *p6 = new Person[3]{}; // 3个Person对象的成员变量都初始化为0
return 0;
}
如果自定义了构造函数,除了全局区 其他内存空间的成员变默认都不会被初给化,需要开发人员手动初始化。
手动请零:
struct Person
{
int id;
Person()
{
memset(this, 0 sizeof(Person));
}
};