【C++ 面试 - 内存管理】每日 3 题(一)

✍个人博客:Pandaconda-CSDN博客

📣专栏地址:http://t.csdnimg.cn/fYaBd

📚专栏简介:在这个专栏中,我将会分享 C++ 面试中常见的面试题给大家~

❤️如果有收获的话,欢迎点赞👍收藏📁,您的支持就是我创作的最大动力💪

1. 简要 说明 C++ 的内存分区

C++ 中的内存分区,分别是堆、栈、自由存储区、全局/静态存储区、常量存储区和代码区。

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

:就是那些由 malloc 等分配的内存块,和堆是十分相似的,不过是用 free 来结束自己的生命**(new 也可以在堆上分配内存)**。

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

全局/静态存储区:全局变量和静态变量被分配到同一块内存中,在以前的 C 语言中,全局变量和静态变量又分为初始化的和未初始化的,在 C++ 里面没有这个区分了,它们共同占用同一块内存区,在该区定义的变量若没有初始化,则会被自动初始化,例如 int 型变量自动初始为 0。

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

代码区:存放函数体的二进制代码。

2. C+ + 中类的数据成员和成员函数内存分布情况

C++ 类是由结构体发展得来的,所以他们的成员变量(C 语言的结构体只有成员变量)的内存分配机制是一样的。下面我们以类来说明问题,如果类的问题通了,结构体也也就没问题啦。类分为成员变量和成员函数,我们先来讨论成员变量。

一个类对象的地址就是类所包含的这一片内存空间的首地址,这个首地址也就对应具体某一个成员变量的地址。(在定义类对象的同时这些成员变量也就被定义了),举个例子:

cpp 复制代码
#include <iostream>
using namespace std;

class Person
{
public:
    Person()
    {
        this->age = 23;
    }
    void printAge()
    {
        cout << this->age <<endl;
    }
    ~Person(){}
public:
    int age;
};

int main()
{
    Person p;
    cout << "对象地址:"<< &p <<endl;
    cout << "age地址:"<< &(p.age) <<endl;
    cout << "对象大小:"<< sizeof(p) <<endl;
    cout << "age大小:"<< sizeof(p.age) <<endl;
    return 0;
}
//输出结果
//对象地址:0x7fffec0f15a8
//age地址:0x7fffec0f15a8
//对象大小:4
//age大小:4

从代码运行结果来看,对象的大小和对象中数据成员的大小是一致的,也就是说,成员函数不占用对象的内存。这是因为所有的函数都是存放在代码区的,不管是全局函数,还是成员函数。

要是成员函数占用类的对象空间,那么将是多么可怕的事情:定义一次类对象就有成员函数占用一段空间。

我们再来补充一下静态成员函数的存放问题:静态成员函数与一般成员函数的唯一区别就是没有 this 指针,因此不能访问非静态数据成员。

就像我前面提到的,所有函数都存放在代码区,静态函数也不例外。所以有人一看到 static 这个单词就主观的认为是存放在全局数据区,那是不对的。

3. 介绍一下内存 对齐

  1. **自然对齐边界:**对于基本数据类型,其自然对齐边界通常为其大小。例如,char 型的自然对齐边界为 1 字节, short 为 2 字节, int 和 float 为 4 字节, double 和 64 位指针为 8 字节。具体数值可能因编译器和平台而异。

  2. **结构体对齐:**结构体内部的每个成员都根据其自然对齐边界进行对齐。也就是可能在成员之间插入填充字节。结构体本身的总大小也会根据其最大对齐边界的成员进行对齐(比如结构体成员包含的最长类型为 int 类型,那么整个结构体要按照 4 的倍数对齐),以便在数组中正确对齐。

  3. **联合体对齐:**联合体的对齐边界取决于其最大对齐边界的成员。联合体的大小等于其最大大小的成员,因为联合体的所有成员共享相同的内存空间。

  4. **编译器指令:**可以使用编译器指令 (如 #pragma pack ) 更改默认的对齐规则。这个命令是全局生效的。这可以用于减小数据结构的大小,但可能会降低访问性能。

  5. **对齐属性:**在 C++11 及更高版本中,可以使用 alignas 关键字为数据结构或变量指定对齐要求。这个命令是对某个类型或者对象生效的。例如, alignas(16) int x; 将确保 x 的地址是 16 的倍数。

  6. **动态内存分配:**大多数内存分配函数 (如 malloc 和 new ) 会自动分配足够对齐的内存,以满足任何数据类型的对齐要求。

相关推荐
小tenten8 分钟前
js延迟for内部循环方法
开发语言·前端·javascript
程序员大金11 分钟前
基于SpringBoot+Vue+MySQL的垃圾分类回收管理系统
java·vue.js·spring boot·后端·mysql·mybatis
CJH~16 分钟前
Java入门:09.Java中三大特性(封装、继承、多态)01
java·开发语言·单例模式
我的运维人生18 分钟前
JavaScript在网页设计中的应用案例
开发语言·javascript·ecmascript·运维开发·技术共享
coding侠客18 分钟前
Spring Boot 注解探秘:常用配置值读取注解的魔力
java·spring boot·后端·spring·spring cloud
计算机学姐20 分钟前
基于Python的可视化在线学习系统
开发语言·vue.js·后端·python·学习·mysql·django
计算机学姐21 分钟前
基于Python的电影票房数据分析系统
开发语言·vue.js·hive·后端·python·spark·django
qincjun22 分钟前
数据库第一章:库的操作
c语言·数据库·c++
Zhichao_9725 分钟前
【UE5 C++课程系列笔记】02——创建C++类的三种方式
c++·笔记·ue5
四代水门27 分钟前
UE5引擎工具链知识点
c++·ue5