c++的类型会占用内存占用最少的浏览器吗

请问在C++中BOOL类型的变量占用的空间是不是可以认为和char一样【c++吧】_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:294,890贴子:
请问在C++中BOOL类型的变量占用的空间是不是可以认为和char一样收藏
如题,就是如果和char一样的话,那么我们声明char岂不是更好,而且比bool表示的还要多
c++培训课程,美国上市公司&达内&出品c++课程,15年教学经验,总监级c++讲师亲授!!达内首创&先就业后付款&模式.名企项目总监授课,成就&稀缺级&c/c++软件工程师
请问在C++中 int* 类型的变量占用的空间是不是可以认为和 long 一样如题,就是如果和 long 一样的话,那么我们声明 long 岂不是更好,而且比 int* 表示的还要多
养一只楼主和养一头猪是不是也一样?
win64,啪啪
那我再来说一下我的问题吧。就是,如果bool类型占一个字节的话,那么声明bool数组的时候会不会对占用的空间进行合并,还是跟char一样的呢?比如我声明了长度为8的bool类型数组,那么占用的空间是1字节还是像char一样8个字节呢?
除了true和false你还要表示什么?
bool类型除了用于表示判断的结果是否成立还有其他作用吗?
C++哪有真正的BOOL类型?你看到的BOOL只是typedef出来的而已,拿什么类型typedef它,它自然就是什么类型的
登录百度帐号推荐应用《C++中类对象的内存布局和占用空间》《C++ 类里面,函数占用存储空间问题 》 demo...
我的图书馆
《C++中类对象的内存布局和占用空间》《C++ 类里面,函数占用存储空间问题 》 demo...
《C++中类对象的内存布局和占用空间》
很多C++书籍中都介绍过,一个Class对象需要占用多大的内存空间。最权威的结论是:
*非静态成员变量总合。
*加上编译器为了CPU计算,作出的数据对齐处理。
*加上为了支持虚函数,产生的额外负担。
介绍完了理论知识后,再看看再找一个例子看看(注:一下所有结果都是在VC6.0 开发环境中得出的结论)
一、空类的Size
void main()
&&&&&& int size = 0;
&&&&&& Car objC
&&&&&& size = sizeof(objCar);
printf("%s %d /r", "Class Car Size:", size);
输出结果:Class Car Size:1
这是为何呢?我想对于这个问题,不仅是刚入行不久的开发新手,就算有过几年以上C++开发经验的开发人员也未必能说清楚这个。
编译器在执行Car objC这行代码后需要,作出一个Class Car的Object。并且这个Object的地址还是独一无二的,于是编译器就会给空类创建一个隐含的一个字节的空间。
二、只有成员变量的Size
&&&&&& int nL
&&&&&& int nW
void main()
&&&&&& int size = 0;
&&&&&& Car objC
&&&&&& size = sizeof(objCar);
&&&&&& printf("%s %d /r", "Class Car Size:", size);
输出结果:Class Car Size:8
这个结果很多开发人员都清楚。在32位系统中,整型变量占4个字节。这里Class Car中含有两个整型类型的成员变量,所以Class Size是8。
&&&&&& int nL
&&&&&& int nW
&&&&&& static int sH
void main()
&&&&&& int size = 0;
&&&&&& Car objC
&&&&&& size = sizeof(objCar);
&&&&&& printf("%s %d /r", "Class Car Size:", size);
输出结果:Class Car Size:8
我们这次在Class Car中添加了一个静态成员变量,但是Class Size仍然是8个字节。这正好符合了,结论中的第一条:非静态成员变量总合。
&&&&&& char chLogo
&&&&&& int nL
&&&&&& int nW
&&&&&& static int sH
void main()
&&&&&& int size = 0;
&&&&&& Car objC
&&&&&& size = sizeof(objCar);
&&&&&& printf("%s %d /r", "Class Car Size:", size);
输出结果:Class Car Size:12
在类中又插入了一个字符型变量,结果Class Size变成了12。这个就是编译器额外添加3个字符变量,做数据对齐处理,为了是提高CPU的计算速度。编译器额外添加的东西我们是无法看见的。这也符合了结论中的第二条:加上编译器为了CPU计算,作出的数据对齐处理。
既然,我们这样定义类成员数据编译器会额外的增加空。那么,我们何不在定义类的时候就考虑到数据对齐的问题,可以多定义出3个字符类型变量作为预留变量,既能满足数据对齐的要求,也给自己的程序添加了一些可扩展的空间。
三、只有成员函数的Size
&&&&&& Car(){};
&&&&&& ~Car(){};
&&&&&& void Fun(){};
void main()
&&&&&& int size = 0;
&&&&&& Car objC
&&&&&& size = sizeof(objCar);
&&&&&& printf("%s %d /r", "Class Car Size:", size);
输出结果:Class Car Size:1
噢,这是怎么回事儿呢?再做一个实验看看。
&&&&&& Car(){};
&&&&&& ~Car(){};
&&&&&& void Fun(){};
&&&&&& int nL
&&&&&& int nW
void main()
&&&&&& int size = 0;
&&&&&& Car objC
&&&&&& size = sizeof(objCar);
&&&&&& printf("%s %d /r", "Class Car Size:", size);
输出结果:Class Car Size:8
这次应该很清楚的了。函数是不占用类空间的。第一个例子中的Size为1个字节,正是编译器为类创建一个隐含的一个字节的空间
&&&&&& Car(){};
&&&&&& virtual ~Car(){};
&&&&&& void Fun(){};
void main()
&&&&&& int size = 0;
&&&&&& Car objC
&&&&&& size = sizeof(objCar);
&&&&&& printf("%s %d /r", "Class Car Size:", size);
输出结果:Class Car Size:4
这次,让析构函数为虚函数,看到了Class Size为4。这正是指向Virtual Table的指针vptr的Size。这正好符合了,结论中的第三条:加上为了支持虚函数,产生的额外负担。
到此为止,一个Class Object究竟占用多少内存空间,已经完全说清楚了。但是,这只是针对单独类,或者说是基类适用。对于子类,却不一样了。有兴趣的朋友可以做一些实验。
《C++ 类里面,函数占用存储空间问题 》
先看两段代码:
int print(){ cout&&"This is A"&&}
inr main()
cout && "Size of A = " && sizeof(a) &&
输出结果:
Size of A =1
int print1(){ cout&&"This is A"&&}
int print2(){ cout&&"This is A"&&}
int print3(){ cout&&"This is A"&&}
inr main()
cout && "Size of A = " && sizeof(a) &&
输出结果:
Size of A =1
对象的大小是它的数据成员所占存储空间之和,就和结构体一样。类中的函数是所有该类对象通用的方法,不算作对象的成员,因此也不算在对象的存储空间内
问题:类里面不管有多少个函数,这个类的对象只占1个字节的内存。这个字节的内存的内容是什么?是指针吗?指针不是占4个字节吗?
当类中类有定义任何变量的时候,类的对象都是1个字节的,当类中没有任何变量的时候,这个类里没有任何真正的成员变量,所以大小应该是0,但0大小不好在内存中定位一个地址,所以,就规定它大小为0的对象要占一字节空间,以便让它拥有一个合法的地址。如果是有派生类的,还有考虑到内存对齐的问题的。
另外涉及到虚函数的话又不一样了。如
virtual int print(){ cout&&"This is A"&&}
如果sizeof(A)的话,得出的是4。
原因是涉及到虚函数的实现问题。
class Class1
&&& m_data1;
&& m_data2;
& virtual vfunc1()
& virtual vfunc2()
& virtual vfunc3()
Class1对象实例
通过vptr指针找到虚函数表
Vtable(虚函数表)
(*vfunc1)()
(*vfunc2)()
(*vfunc3)()
Class1::vfunc1()
Class1::vfunc2()
Class1::vfunc3()
所以回到原来的问题,A中只有一个或者几个虚函数的话,没有成员变量,那么类A相当于含有一个vptr指向虚函数表的指针,所以sizeof(A)=4。
还有一点,如
class C:public B
class D:public virtual B
class E:public B,public B2
sizeof(B) = 1;&& sizeof(B2) = 1;& sizeof(C) = 1;& sizeof(D) = 4;& sizeof(E) = 1;
空类所占空间为一(上文以解释),单一继承的空类空间也是1,多重继承的空类空间还是1,但是虚继承涉及到虚表(虚指针),所以sizeof(D)=4。
TA的最新馆藏[转]&[转]&[转]&[转]&
喜欢该文的人也喜欢C++(虚)继承类的内存占用大小 - CSDN博客
C++(虚)继承类的内存占用大小
首先,平时所声明的类只是一种类型定义,它本身是没有大小可言的。 因此,如果用sizeof运算符对一个类型名操作,那得到的是具有该类型实体的大小。
计算一个类对象的大小时的规律:
1、空类、单一继承的空类、多重继承的空类所占空间大小为:1(字节,下同);
2、一个类中,虚函数本身、成员函数(包括静态与非静态)和静态数据成员都是不占用类对象的存储空间的;
3、因此一个对象的大小≥所有非静态成员大小的总和;
4、当类中声明了虚函数(不管是1个还是多个),那么在实例化对象时,编译器会自动在对象里安插一个指针vPtr指向虚函数表VTable;
5、虚承继的情况:由于涉及到虚函数表和虚基表,会同时增加一个(多重虚继承下对应多个)vfPtr指针指向虚函数表vfTable和一个vbPtr指针指向虚基表vbTable,这两者所占的空间大小为:8(或8乘以多继承时父类的个数);
6、在考虑以上内容所占空间的大小时,还要注意编译器下的“补齐”padding的影响,即编译器会插入多余的字节补齐;
7、类对象的大小=各非静态数据成员(包括父类的非静态数据成员但都不包括所有的成员函数)的总和+ vfptr指针(多继承下可能不止一个)+vbptr指针(多继承下可能不止一个)+编译器额外增加的字节。
示例一:含有普通继承
前面三个A、B、C类的内存占用空间大小就不需要解释了,注意一下内存对齐就可以理解了。
求sizeof(D)的时候,需要明白,首先VPTR指向的虚函数表中保存的是类D中的两个虚函数的地址,然后存放基类C中的两个数据成员ch1、ch2,注意内存对齐,然后存放数据成员d,这样4+4+4=12。
求sizeof(E)的时候,首先是类B的虚函数地址,然后类B中的数据成员,再然后是类C的虚函数地址,然后类C中的数据成员,最后是类E中的数据成员e,同样注意内存对齐,这样4+4+4+4+4=20。
示例二:含有虚继承
sizeof(Derived)=32,其在内存中分布的情况如下:
执行结果:A’s size is 8
& & & & & & & & & & & & B’s size is 16
说明:对于虚继承,类B因为有自己的虚函数,所以它本身有一个虚指针,指向自己的虚表。另外,类B虚继承类A时,首先要通过加入一个虚指针来指向父类A,然后还要包含父类A的所有内容。因此是4+4+8=16。
两种多态实现机制及其优缺点
除了c++的这种多态的实现机制之外,还有另外一种实现机制,也是查表,不过是按名称查表,是smalltalk等语言的实现机制。这两种方法的优缺点如下:
(1)、按照绝对位置查表,这种方法由于编译阶段已经做好了索引和表项(如上面的call *(pa-&vptr[1]) ),所以运行速度比较快;缺点是:当A的virtual成员比较多(比如1000个),而B重写的成员比较少(比如2个),这种时候,B的vtableB的剩下的998个表项都是放A中的virtual成员函数的指针,如果这个派生体系比较大的时候,就浪费了很多的空间。
比如:GUI库,以MFC库为例,MFC有很多类,都是一个继承体系;而且很多时候每个类只是1,2个成员函数需要在派生类重写,如果用C++的虚函数机制,每个类有一个虚表,每个表里面有大量的重复,就会造成空间利用率不高。于是MFC的消息映射机制不用虚函数,而用第二种方法来实现多态,那就是:
(2)、按照函数名称查表,这种方案可以避免如上的问题;但是由于要比较名称,有时候要遍历所有的继承结构,时间效率性能不是很高。
3、总结:
如果继承体系的基类的virtual成员不多,而且在派生类要重写的部分占了其中的大多数时候,用C++的虚函数机制是比较好的;但是如果继承体系的基类的virtual成员很多,或者是继承体系比较庞大的时候,而且派生类中需要重写的部分比较少,那就用名称查找表,这样效率会高一些,很多的GUI库都是这样的,比如MFC,QT。PS:其实,自从计算机出现之后,时间和空间就成了永恒的主题,因为两者在98%的情况下都无法协调,此长彼消;这个就是计算机科学中的根本瓶颈之所在。软件科学和算法的发展,就看能不能突破这对时空权衡了。呵呵。。
何止计算机科学如此,整个宇宙又何尝不是如此呢?最基本的宇宙之谜,还是时间和空间。
C++如何不用虚函数实现多态,可以考虑使用函数指针来实现多态
这样做的好处主要是绕过了vtable。我们都知道虚函数表有时候会带来一些性能损失。
转载地址:
本文已收录于以下专栏:
相关文章推荐
本实例以经典的菱形多重继承、虚继承为例,研究类对象的大小,假设有以下的虚继承实例代码:
class Point2d
float _x,_y;
class Vert...
一、真空类
class CNull
内存结构:
评注:长度其实为0,这个字节作为内容没有意义,可...
1. 在 64 位 Linux 下,结构体字段默认按 8 字节对齐;32 位 Linux 下,默认 4 字节对齐。
2. 显示指定对齐方式时,会受到机器字长的约束,即 64 位 Linux 下可以按...
本文从5段代码实例出发,通过类中类的普通继承,类的虚继承,类的多重继承,多个虚函数类的普通继承、虚继承与多重继承,几个交叉概念,详细的阐释了继承、虚函数与虚继承的基本概念,深入剖析了继承于虚继承的区别...
一、虚函数的工作原理
虚函数的实现要求对象携带额外的信息,这些信息用于在运行时确定该对象应该调用哪一个虚函数。典型情况下,这一信息具有一种被称为 vptr(virtual table po...
C++ 对象的内存布局(下) 陈皓http://blog.csdn.net/haoel
<<<点击这里查看上篇
重复继承 下面我们再来看看,发生重复继承的情况。所谓重复继承,也就是某个基类被...
首先重新回顾一下关于类/对象大小的计算原则:
类大小计算遵循结构体对齐原则
第一个数据成员放在offset为0的位置
其它成员对齐至min(sizeof(member),#pragm...
C++ 对象的内存布局(上) 陈皓http://blog.csdn.net/haoel
点击这里查看下篇>>>前言 07年12月,我写了一篇《C++虚函数表解析》的文章,引起了大家的兴趣。有很多朋友...
1、VS2012使用命令行选项查看对象的内存布局
微软的Visual Studio提供给用户显示C++对象在内存中的布局的选项:/d1reportSingleClassLayout。使用...
多重继承和虚继承的内存布局刺猬@http://blog.csdn.net/littlehedgehog
这篇文章主要讲解虚继承的C++对象内存分布问题,从中也引出了dynamic_ca...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)64被浏览3476分享邀请回答133 条评论分享收藏感谢收起154 条评论分享收藏感谢收起查看更多回答C/C++编译的程序占用的内存情况详细解析 - CSDN博客
C/C++编译的程序占用的内存情况详细解析
一个由C/C++编译的程序占用的内存分为以下几个部分
  1、栈区(stack)— 由自动分配释放 ,存放的参数值,的值等。其操作方式类似于数据结构中的栈。
&&&&&& 堆(heap):由malloc,new等分配的空间的地址,地址由低向高增长(程序员释放)。
  2、堆区(heap) — 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于。
&&&&&& 栈(stack):是自动分配变量,以及函数调用所使用的一些空间(所谓的局部变量),地址由高向低减少;
  3、全局区(静态区)(static)— 全局变量和的存储是放在一块的,初始化的和静态变量在一块区域,
未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。--&分别是data区,bbs区&
  4、文字常量区 — 常量字符串就是放在这里的,程序结束后由系统释放 。--&coment区
  5、程序代码区 — 存放函数体的二进制代码。--&code区
二、例子程序
这是一个前辈写的,非常详细
//main.cpp
int a = 0;// 全局初始化区
char *p1; //全局未初始化区
char s[] = &abc&; //栈
char *p2; 栈
char *p3 = &123456&; //在常量区,p3在栈上。
static int c =0;// 全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配 得来得10和20字节的区域就在堆区。
strcpy(p1, &123456&); 放在常量区,编译器可能会将它与p3所指向的&123456&优化成一个地方。
在函数体中定义的变量通常是在栈上,用malloc, calloc, realloc等分配内存的函数分配得到的就是在堆上。在所有函数体外定义的是全局量,加了static修饰符后不管在哪里都存放在全局区(静态区),在所有函数体外定义的static变量表示在该文件中有效,不能extern到别的文件用,在函数体内定义的static表示只在该函数体内有效。另外,函数中的
&adgfdf &这样的字符串存放在常量区。
还有就是函数调用时会在栈上有一系列的保留现场及传递参数的操作。栈的空间大小有限定,vc的缺省是2M。栈不够用的情况一般是程序中分配了大量数组和递归函数层次太深。有一点必须知道,当一个函数调用完返回后它会释放该函数中所有的栈空间。栈是由编译器自动管理的,不用你操心。堆是动态分配内存的,并且你可以分配使用很大的内存。但是用不好会产生内存泄漏。并且频繁地malloc和free会产生内存碎片(有点类似磁盘碎片),因为c分配动态内存时是寻找匹配的内存的。而用栈则不会产生碎片。在栈上存取数据比通过指针在堆上存取数据快些
堆(heap)和栈(stack)是C/C++编程不可避免会碰到的两个基本概念。首先,这两个概念都可以在讲数据结构的书中找到,他们都是基本的数据结构,虽然栈更为简单一些。在具体的C/C++编程框架中,这两个概念并不是并行的。对底层机器代码的研究可以揭示,栈是机器系统提供的数据结构,而堆则是C/C++函数库提供的。具体地说,现代计算机(串行执行机制),都直接在代码底层支持栈的数据结构。这体现在,有专门的寄存器指向栈所在的地址,有专门的机器指令完成数据入栈出栈的操作。这种机制的特点是效率高,支持的数据有限,一般是整数,指针,浮点数等系统直接支持的数据类型,并不直接支持其他的数据结构。因为栈的这种特点,对栈的使用在程序中是非常频繁的。对子程序的调用就是直接利用栈完成的。机器的call指令里隐含了把返回地址推入栈,然后跳转至子程序地址的操作,而子程序中的ret指令则隐含从堆栈中弹出返回地址并跳转之的操作。C/C++中的自动变量是直接利用栈的例子,这也就是为什么当函数返回时,该函数的自动变量自动失效的原因。
和栈不同,堆的数据结构并不是由系统(无论是机器系统还是操作系统)支持的,而是由函数库提供的。基本的malloc/realloc/free函数维护了一套内部的堆数据结构。当程序使用这些函数去获得新的内存空间时,这套函数首先试图从内部堆中寻找可用的内存空间,如果没有可以使用的内存空间,则试图利用系统调用来动态增加程序数据段的内存大小,新分配得到的空间首先被组织进内部堆中去,然后再以适当的形式返回给调用者。当程序释放分配的内存空间时,这片内存空间被返回内部堆结构中,可能会被适当的处理(比如和其他空闲空间合并成更大的空闲空间),以更适合下一次内存分配申请。这套复杂的分配机制实际上相当于一个内存分配的缓冲池(Cache),使用这套机制有如下若干原因:
1. 系统调用可能不支持任意大小的内存分配。有些系统的系统调用只支持固定大小及其倍数的内存请求(按页分配);这样的话对于大量的小内存分类来说会造成浪费。
2. 系统调用申请内存可能是代价昂贵的。系统调用可能涉及用户态和核心态的转换。
3. 没有管理的内存分配在大量复杂内存的分配释放操作下很容易造成内存碎片。
三、堆和栈的理论知识
2.1申请 方式
由系统自动分配 。 例如,声明在函数中一个局部变量 系统自动在栈中为b开辟空间
需要程序员自己申请,并指明大小,在c中malloc函数
如p1 = (char *)malloc(10);
在C++ 中用new运算符
如p2 = (char *)malloc(10);
但是注意 p1、p2本身是在栈中的。
申请后系统的响应
栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存 ,否则将报异常提示栈溢出。
堆:首先应该知道操作系统有一个记录空闲内存 地址的链表,当系统 收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配 给程序,另外,对于大多数系统,会在这块内存 空间中的首地址处记录
本次分配 的大小,这样,代码中的delete语句才能正确的释放本内存 空间。另外,由于找到的堆结点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表 中。
2.3申请大小的限制
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存 的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在WINDOWS下,栈的大小是 2M(也有的说是1M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存 。由此可见,堆获得的空间比较灵活,也比较大。
2.4申请效率的比较:
栈由系统自动分配 ,速度较快。但程序员是无法控制的。
堆是由 new分配 的内存 ,一般速度比较慢,而且容易产生内存 碎片,不过用起来最方便.
另外,在 WINDOWS下,最好的方式是用VirtualAlloc分配 内存 ,他不是在堆,也不是在栈是直接在进程的地址空间中保留一快内存 ,虽然用起来最不方便。但是速度快,也最灵活。
2.5堆和栈中的存储内容
栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由 右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数 调用结束后,局部变量先出栈,然后是参数,最后栈顶指针 指向最开始存的地址,也就是主函 数中的下一条指令,程序由该点继续运行。
堆:一般是在 堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。
2.6存取 效率的比较
char s1[] = &aaaaaaaaaaaaaaa&;
char *s2 = &bbbbbbbbbbbbbbbbb&;
aaaaaaaaaaa 是在运行时刻赋值的;
而 bbbbbbbbbbb是在编译时就确定的;
但是,在以后 的存取中,在栈上的数组 比指针 所指向的字符 串(例如堆)快。
#i nclude
void main()
char a = 1;
char c[] = &&;
char *p =&&;
对应的汇编代码
10: a = c[1];
A 4D F1 mov cl,byte ptr [ebp-0Fh]
4D FC mov byte ptr [ebp-4],cl
11: a = p[1];
B 55 EC mov edx,dword ptr [ebp-14h]
A 42 01 mov al,byte ptr [edx+1]
45 FC mov byte ptr [ebp-4],al
第一种在读取 时直接就把字符 串中的元素读到寄存器cl中,而第二种则要先把指针 值读到edx中,在根据edx读取字符 , 显然慢了。
堆和栈的区别可以用如下的比喻来看出:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使 用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但自由度小。
使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的 口味,而且自由度大。
从以上知识可知,栈是系统提供的功能,特点是快速高效,缺点是有限制,数据不灵活;而栈是函数库提供的功能,特点是灵活方便,数据适应面广泛,但是效率有一定降低。栈是系统数据结构,对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一。不同堆分的内存无法互相操作。栈空间分静态分配和动态分配两种。静态分配是编译器完成的,比如自动变量(auto)的分配。动态分配由alloca函数完成。栈的动态分配无需释放(是自动),也就没有释放函数。为可移植的程序起见,栈的动态分配操作是不被鼓励的!堆空间的分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存/释放内存匹配是良好程序的基本要素。
操作系统方面的堆和栈,如上面说的那些,不多说了。还有就是数据结构方面的堆和栈,这些都是不同的概念。这里的堆实际上指的就是(满足堆性质的)优先队列的一种数据结构,第1个元素有最高的优先权;栈实际上就是满足先进后出的性质的数学或数据结构。虽然堆栈,堆栈的说法是连起来叫,但是他们还是有很大区别的,连着叫只是由于历史的原因。
堆和栈的生长方向恰好相反,
|--------------| 低地址
|--------------|
| 栈 | 高地址
-----------------
所以计算机中的堆和栈经常时放一块讲的
一般不是必要就不要动态创建,最讨厌把new出来的东西当局部变量用,用万了马上delete 的做法.
1.栈分配比堆快,只需要一条指令就呢给配所有的局部变量
2.栈不会出现内存碎片
3.栈对象好管理
当然,某些情况下也要那么写,比如
1.对象很大
2.对象需要在某个特定的时刻构造或析够
3.类只允许对象动态创建,比如VCL的大多数类
当然,必须用堆对象时也不能躲避
堆内存和栈内存各有什么作用?堆:顺序随意&&栈:先进后出
----------------------------------------------------------------------------------------------------------------------
为什么说在堆上分配 内存 比在栈上分配 内存 慢?堆空间的开辟需要用系统函数,栈上直接修改指针
堆空间的需 要系统记帐,栈上的空间可以由编译器管理或是保存在某个处理器寄存器中。
堆空间的释放需要系统管理,栈上的释放可以直接丢弃。堆空间需要通过栈上的指针 间接引用,所以访问会慢
记得在apue2上面看到关于线程中有这样一段话,大致意思是,一个 线程有自己的堆栈,可以在堆栈上分配 内存 ,比如说一个结构体,如果这个线程调用了pthread_exit()返回这个结构体指针 的时候之后要特别的小心,因为很有可能这个结构体里面的成员值发生改变,这个可以理解,因为同一个进程所 有线程的资源是共享的,当这个线程退出之后那部分以前用过的堆栈很可能被其它线程占用,但同时又说如果malloc就不会出现这样的问题,
比如,在栈上分一个int,只要esp-4就可以了,
在堆上系统要记录被分配 内存 的信息,以便释放
----------------------------------
内存 分配 方式有三种:&&&
&& 1.从静态存储区域分配 。内存 在程序编译的时候就已经分配 好,这块内存 在程序的整个运行期间都存在。例如全局变 量,static变量。&&&
&& 2.在栈上创建。在执行函数时,函数内局部变量的存储单元 都可以在栈上创建,函数执行结束时这些存储单元 自动被 释放。栈内存 分配 运算内置于处理器的指令集中,效率很 高,但是分配 的内存 容量有限。&&&
&& 3.从堆上分配 ,亦称动态内存 分配 。程序在运行的时候用malloc或new申请任意多少的内存 ,程 序员自己负责在何时用free或delete释放内存 。动态内存 的生存期由我们决定,使用非常灵活,但问题也最多。
----------------------------------------
一般所说的堆栈(stack)往往是指栈,先进后出, 它是一块内存 区。用以存放程序的局部变量,临时变量,函数的参数,返回地址等。在这块区域中的变量的分配 和释放由系统自动进行。不需要用户的参与。&&&
&& 而在堆(heap,先进先出) 上的空间则是由用户进行分配 ,并由用 户负责释放。
===================================================================================
本文已收录于以下专栏:
相关文章推荐
1,从静态存储区域分配;
内存在程序编译时已经分配好,这块内存在程序的整个运行期间都存在。速度快、不容易出错,因为有系统会善后。例如全局变量,static变量等。
2,在栈上分配
在执行函数时,...
转自:http://blog.chinaunix.net/uid-9688646-id-3087625.html
一个由C/C++编译的程序占用的内存分为以下几个部分 
1、栈区(stack)...
一、预备知识—程序的内存分配       堆(heap)和栈(stack)是C/C++编程不可避免会碰到的两个基本概念。首先,这两个概念都可以在讲数据结构的书中找到,他们都是基本的数据结构,虽然栈更为...
一个由C/C++编译的程序占用的内存分为以下几个部分
1、栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
2、堆区(heap)...
转自: http://blog.chinaunix.net/uid-9688646-id-3087625.html
一个由C/C++编译的程序占用的内存分为以下几个部分 
1、栈区(s...
转自http://www.jb51.net/article/41723.htm
1. malloc()函数
1.1 malloc的全称是memory allocation,中文叫动态内存分配。
C/C++中函数形参是多重指针的详细解释
由于内存的资源有限,不可能无限制地为变量分配内存,合理地组织程序中变量的内存分配是程序设计人员必须要考虑的问题,而要合理分配内存我们需要知道程序在内存中的分区情况,本文较为详细地介绍了C程序在内存中的...
他的最新文章
讲师:何宇健
讲师:董岩
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)

我要回帖

更多关于 占用内存小的浏览器 的文章

 

随机推荐