C++中new Points、new Points()与new Points{}内存占用差异原因咨询
为什么
new Points;看起来不占用内存? 这其实是C++初始化规则和Linux内存惰性分配机制共同作用的结果,咱们一步步拆解:
1. 三种new写法的本质差异
首先得明确C++里这三种初始化方式的核心区别:
new Points{};和new Points();属于值初始化:
如果Points是POD类型(比如没有自定义构造函数、成员都是基本类型的结构体),编译器会自动把所有成员初始化为零值;如果有自定义默认构造函数,就会调用该构造函数完成初始化。new Points;属于默认初始化:
如果Points是POD类型,编译器不会生成任何初始化代码,对象的成员会是未定义的垃圾值;如果有自定义默认构造函数,效果和前两种完全一致,都会调用构造函数。
2. Linux的惰性内存分配是关键
Ubuntu基于的Linux内核采用惰性内存分配策略:当你调用new申请内存时,内核只是给你的进程分配了一段虚拟内存地址空间,但并不会立刻把物理内存页分配给你——只有当你第一次读写这段内存的时候,内核才会真正分配物理内存,并建立虚拟地址到物理内存的映射。
3. 为什么内存占用表现不同?
结合上面两点,你的情况应该是Points是一个POD类型(比如包含大量数组的结构体):
- 当你用
new Points{};或new Points();时,值初始化会触发对所有成员的写操作(把它们置零),这就会立刻触发内核分配物理内存,所以你能看到可用内存明显减少。 - 当你用
new Points;时,默认初始化不会对成员做任何操作,这段虚拟内存没有被读写过,内核也就没有分配物理内存。此时进程的虚拟内存确实占用了对应大小,但物理内存还没被实际分配,所以你查看可用内存时看不到变化——并不是真的没占用内存,只是物理内存还没被“兑现”而已。
验证方法
你可以做个小实验:在p = new Points;之后,随便访问一个成员(比如p->some_member = 0;),这时候再去看可用内存,就会发现它的占用和前两种写法完全一致了——因为读写操作触发了物理内存的分配。
额外说明
如果Points有自定义的默认构造函数,那么三种写法都会调用构造函数,只要构造函数里有内存读写操作,内存占用就会是一样的。你的案例能出现差异,核心就是Points是POD类型,且默认初始化没有触发任何内存访问。
内容的提问来源于stack exchange,提问作者Erel Segal-Halevi
相关产品推荐
相关产品推荐

