C++内存管理

内存分区

  • 栈区:
  • 堆区:由new/malloc分配的内存块,不归编译器管,需要程序员手动释放(程序结束后会自动被操作系统回收)
  • 全局/静态变量区:静态变量(局部static变量和全局static变量)、全局变量和常量
  • 常量区:常量字符串,不允许修改
  • 代码区:函数体

类的内存存储

  1. 类中非静态成员的大小之和
  2. 编译器加入的额外成员变量(如指向虚函数表的指针)
  3. 内存对齐所加的padding
    注:所有的函数都是放在代码区的,包括静态函数

空类的大小是0吗?

空类的大小不为0,编译器不允许空类的大小为0,具体大小由编译器定,如vs设置空类大小为1

#include <iostream>
using namespace std;

class A {

};
int main() {
    A a;
    cout << "sizeof A:" << sizeof(A) << endl;
    cout << "sizeof a:" << sizeof(a) << endl;
}
/*结果
sizeof A:1
sizeof a:1
*/

带有虚函数的空类大小不为0,因为有虚函数指针的存在

#include <iostream>
using namespace std;

class A {
	virtual void show(){}
};
int main() {
    A a;
    cout << "sizeof A:" << sizeof(A) << endl;
    cout << "sizeof a:" << sizeof(a) << endl;
}
/*结果
sizeof A:8
sizeof a:8
*/

new的三种用法

1. plain new
申请失败抛出std::bad_alloc异常

2. nothrow new
不抛出异常,如果失败侧返回NULL

char* p = new(nothrow) char[10e11];
if(p == NULL) 
{
	cout << "alloc failed" << endl; 
}
delete p;

3. placement new
不申请内存,用于将已经分配成功的内存重新构造成新的对象或对象数组。

int* p = new int[4];
string str = new(p) string;

内存池

this指针的用法

  • this指针是类的指针,指向对象的首地址
  • this指针只能在成员函数中使用,在全局函数、静态函数中都不能使用
  • this指针只有在成员函数中才有定义,且存储位置会因编译器不同有不同存储位置

delete this的后果

在类对象的内存空间中,只有数据成员和虚函数表指针,并不包含代码内容,类的成员函数单独放在代码段中。在调用成员函数时,隐含传递一盒this指针,让成员函数知道当前是哪个对象在调用它。当调用delete this时,类对象的内存空间被释放。在delete this之后进行的其他任何函数调用,只要不涉及到this指针的内容,都能够正常运行。一旦涉及到this指针,如操作数据成员,调用虚函数等,就会出现不可预期的问题(虽然delete this释放了类空间的内存空间,但是内存孔家吗却并不是马上被回收到系统中,可能由于缓冲或者其他原因,导致这段内存空间暂时并没有被系统收回,此时这段内存是可以访问的)。

this指针的生命周期:成员函数的开始执行前构造,在成员的执行结束后清除

存放地址:this指针会因编译器不同而有不同的放置位置。可能是栈,也可能是寄存器,甚至全局变量。

this是如何传递类中的函数的?
成员函数也是存储在代码区,每次调用对应对象的成员函数,都会在该函数的参数中添加this指针。
this指针首先入栈,然后成员函数的参数从右向左进行入栈,最后函数返回地址入栈。

posted @ 2025-03-03 18:08  RunTimeErrors  阅读(17)  评论(0)    收藏  举报