每个应用都有自己独立的内存空间,其内存空间一般都有:代码段(代码区)、数据段(全局区)、栈空间、堆空间。

代码段(代码区)

用于存放代码。

数据段(全局区)

用于存放全局变量等。

栈空间

每调用一个函数,就会给它分配一段连续的栈空间,等函数调用完后,就会回收空间。

堆空间

在程序运行过程,为了能够自由控制内存的生命周期、大小,会经常使用堆空间的内存。

堆空间的申请和释放

如果内存够用,会分配一块连续的内存空间出来。

mallocfree

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;
}

注意

  1. newfreemallocdelete不可以混着用!!!否则可能会存在内存泄漏。
  2. 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

image-20210704163517259

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种地方。

  1. 全局区(数据段):全局变量。

  2. 栈空间:函数里面的局部变量。

  3. 堆空间:动态申请内存(mallocnew等)。

    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));
    }
};