C++的内存划分

C++的内存分布

1. 四大区域

通用的是数据区(.data;.bss;常量区)和代码区(.text)。在程序的执行过程中,我们需要创建变量,以及调用函数,从而产生了堆和栈。

在这里插入图片描述

  1. 数据区:
    比如:全局变量,静态变量。包括静态局部变量。
    • .data:用于存储初始化的全局变量、静态变量。这些变量在程序开始执行前就已经被分配和初始化了,它们的值在程序执行过程中可以被修改。
    • .bss:区域用于存储未初始化的全局变量和静态变量。当全局变量以及静态变量被初始化为0或者nullptr的时候也会存放在.bss区。
  2. 代码区(.text区):
    比如:字符串常量。
    .textt区域存储程序的执行代码,即编译后的机器语言指令。这个区域通常是只读的,以防止程序在运行时被意外或恶意修改。
  3. 堆区:
    就是那些由newmalloc分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个new就要对应一个delete。如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
  4. 栈区:
    在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。

2. 例题

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
    static int staticVar = 1;
    int localVar = 1;
    int num1[10] = {1, 2, 3, 4};
    char char2[] = "abcd";
    char* pChar3 = "abcd";
    int* ptr1 = (int*)malloc(sizeof (int)*4);
    int* ptr2 = (int*)calloc(4, sizeof(int));
    int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);
    free (ptr1);
    free (ptr3);
}
1. 选择题:
选项: A.栈 B.堆 C.数据段 D.代码段 
globalVar在哪里?__C__ staticGlobalVar在哪里?__C__ 
staticVar在哪里?__C__ localVar在哪里?__A__
num1 在哪里?__A__char2在哪里?__A__ 
pChar3在哪里?__A__ ptr1在哪里?__A__
2. 填空题:
sizeof(num1) = ____; 40
*char2在哪里?_A__ *pChar3在哪里?__D__ *ptr1在哪里?__B__
sizeof(char2) = ____; 5     strlen(char2) = ____; 4
sizeof(pChar3) = ____; 4    strlen(pChar3) = ____; 4
sizeof(ptr1) = ____; 4

3. 字符串常量、string、char[]

#include <iostream>

int main() {
    // 字符串常量定义在代码中
    const char* str1 = "Hello, World!";
    // 尝试修改字符串常量的内容,这是不允许的
    // str[0] = 'h'; //error
    std::cout << "Address of the const char constant: " << (void*)str1 << std::endl;
    std::cout << "Content of the const char constant: " << str1 << std::endl;
    cout << endl; cout << endl; cout << endl;


    string str2 = "Hello, World!asfdsgefdgqwertyuioasdfghjkzxcvbnm,qwertyuisdfghjkxcvbnm,ertyuidfghjkftgasyhdifjnia";
    std::cout << "Address of the string constant: " << &str2 << std::endl;
    std::cout << "Content of the string constant: " << str2 << std::endl;
    cout << endl;
    str2[0] = 'h';
    std::cout << "Address of the string constant: " << &str2 << std::endl;
    std::cout << "Content of the string constant: " << str2 << std::endl;
    cout << endl; cout << endl; cout << endl;


    char str3[100] = "Hello, World!";
    std::cout << "Address of the char[] constant: " << &str3 << std::endl;
    std::cout << "Content of the char[] constant: " << str3 << std::endl;
    return 0;
}

str2这么长的原因是因为字符串长度较短,std::string 会使用小字符串优化(SSO),这意味着字符串的内容可能直接存储在 str2 对象内部,而不是堆上。

显示结果如下:
在这里插入图片描述

发现const char*的类型地址和string,char[]的地址差距过大。

由此可见他们直接是有区别的。

区别如下:

  1. const char*:
    const char* str = "Hello, World!"; 这行代码中的"Hello, World!"是一个字符串常量,存放在程序的只读数据段。
  2. string:
    • 在函数内部定义的std::string对象通常存储在栈上。std::string是一个类类型,其实例会在栈上分配内存空间。但是,std::string内部通常会动态分配内存来存储实际的字符串数据,这部分数据是存放在上的。
    • 例如,当你在main()函数中创建一个std::string str = "Hello, World!";,str对象的控制结构(如指针、长度和容量等)会存放在栈上,而字符串"Hello, World!"的字符数据会通过堆分配存放。
  3. char[]:
    • 在函数内定义的char[]数组,如char arr[] = "Hello, World!";,数组的内容直接存储在栈上。这包括数组的所有元素,即字符序列。
    • 数组arr的所有字符(包括终结符\0)都会在栈上分配,且在函数执行期间持续存在,直到函数返回。

tips:
小字符串优化(SSO):
SSO是一种用于减少存储短字符串时的内存分配开销的优化技术。在C++中,这种优化通常在实现std::string等字符串类时使用,其中包含一个固定大小的内部缓冲区,用于存储较短的字符串。当字符串长度不超过这个内部缓冲区的容量时,字符串的内容就可以直接存储在这个缓冲区中,而不需要进行堆分配。

  • 23
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值