http://blog.csdn.net/zhanghefu/article/details/5003407

转自:http://blog.csdn.net/wdzxl198/article/details/9050587

明确区分堆和栈

void f() { int* p=new int[]; }

在栈内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中

堆和栈的区别:

管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,申请、释放工作由程序员控制,容易产生memory leak。

空间大小:一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。

碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出

生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向增长;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。

分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。alloca是在栈(stack)上申请空间,用完马上就释放

分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的,例如为了分配一块内存,库函数会按照一定的算法(具体的算法可以参考数据结构/操作系统)在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间即为该进程申请额外的内存,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。

指针与数组

下面以字符串为例比较指针与数组的特性

1)修改内容的方式

char *p = "world";

p[0] = 'x';

cout << p << endl;

字符串是常量,不能修改,编译器不能发现这个错误,运行时出错

2)复制内容及内容比较的方式

不能对数组名进行直接复制与比较。若想把数组a的内容复制给数组b,不能用语句 b = a ,否则将产生编译错误。应该用标准库函数strcpy进行复制。同理,比较b和a的内容是否相同,不能用if(b==a) 来判断,应该用标准库函数strcmp进行比较。

3)计算内存容量

用运算符sizeof可以计算出数组的容量(字节数),C++/C语言没有办法知道指针所指的内存容量。

char a[] = "hello";
char *p = a;
char *q = new char[];
cout << sizeof(a) << endl;
cout << sizeof(p) << endl;
cout << sizeof(q) << endl;

输出为6,4,4

注意当数组作为函数的参数进行传递时,该数组自动退化为同类型的指针

void func(char a[])
{
cout << sizeof(a) << endl;
}
//输出为4

指针参数是如何传递内存

void getMemory(char *p, int num)
{
p = (char *)malloc(sizeof(char)*num);
} void main()
{
char *str = NULL;
getMemory(str, );
strcpy(str,"hello");
system("pause");
}

如果函数的参数是一个指针,不要指望用该指针去申请动态内存。上例中,getMemory(str, 200)并没有使str获得期望的内存,str依旧是NULL.

问题出在函数GetMemory中。编译器总是要为函数的每个参数制作临时副本,指针参数p的副本是 _p,编译器使 _p = p。如果函数体内的程序修改了_p的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_p申请了新的内存,只是把_p所指的内存地址改变了,但是p丝毫未变。所以函数GetMemory并不能输出任何东西。事实上,每执行一次GetMemory就会泄露一块内存,因为没有用free释放内存。

我们可以用函数返回值来传递动态内存

char *getMemory(int num)
{
char *p = (char *)malloc(sizeof(char)*num);
return p;
} void main()
{
char *str = NULL;
str=getMemory();
strcpy(str,"hello");
free(str);
}

这里强调不要用return语句返回指向“栈内存”的指针,因为该内存在函数结束时自动消亡,见示例:

char *getString(void)
{
char p[] = "hello world";
return p;
} void main()
{
char *str = NULL;
str = getString();
cout << str << endl;//输出乱码,因为p是局部变量,函数返回时指向的内存已经销毁
system("pause");
}

malloc/free和new/delete的区别

malloc与free是C++/C语言的标准库函数,new/delete是C++的运算符。它们都可用于申请动态内存和释放内存。

对于非内部数据类型的对象而言,光用maloc/free无法满足动态对象的要求。对象在创建的同时要自动执行构造函数,对象在消亡之前要自动执行析构函数。由于malloc/free是库函数而不是运算符,不在编译器控制权限之内,不能够把执行构造函数和析构函数的任务强加于malloc/free。

32位系统下char int float long double所占字节数分别为1 4 4 4 8

【转】c++内存管理学习纲要的更多相关文章

  1. c++内存管理学习纲要

    本系列文章,主要是学习c++内存管理这一块的学习笔记. 时间:6.7-21 之下以技术内幕的开头语,带入到学习C++内存管理的技术中吧: 内存管理是C++最令人切齿痛恨的问题,也是C++最有争议的问题 ...

  2. C++内存管理学习笔记(5)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  3. C++内存管理学习笔记(6)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  4. C++内存管理学习笔记(7)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  5. C++内存管理学习笔记(4)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  6. C++内存管理学习笔记(3)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  7. C++内存管理学习笔记(2)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  8. C++内存管理学习笔记(1)

    /****************************************************************/ /*            学习是合作和分享式的! /* Auth ...

  9. Linux内存管理学习资料

    下面是Linux内存管理学习的一些资料. 博客 mlock() and mlockall() system calls. All about Linux swap space 逆向映射的演进 Linu ...

随机推荐

  1. 前端什么是BFC

    什么是BFC? 全称块级格式化上下文?什么意思不懂.看了好多博客,基本都是抄的,真心都不是大白话.我今天来总结一下,用菜鸟级别的语言来描述. BFC 应该可以抽象成一个 独立的个体,出淤泥而不染的白莲 ...

  2. jmeter 接口测试简介

    前言: 本文主要针对http接口进行测试,使用Jmeter工具实现. Jmter工具设计之初是用于做性能测试的,它在实现对各种接口的调用方面已经做的比较成熟,因此,本次直接使用Jmeter工具来完成对 ...

  3. index 定义 v-for 未使用变量 实际是没有 :key="index"

    需要有 :key="index" <Checkbox :label="item.key" :key="index" v-for=&qu ...

  4. es6 fs 输出文件 iviewDemo

    // fs.open('./env.js', 'w', function(err, fd) { // // const buf = 'export default "development& ...

  5. 暑假集训 || LCA && RMQ

    LCA定义为对于一颗树 树上两个点的最近公共祖先 一.Tarjan求LCA(离线方法 https://blog.csdn.net/lw277232240/article/details/7701751 ...

  6. Proguard配置文件内容

    -injars elec-bendao-1.2.jar-outjars elec-bendao-1.2-end.jar -libraryjars lib\charsets.jar-libraryjar ...

  7. EBS oracle 批量导入更新MOQ(最小拆分量、采购提前期、最小订购量、最小包装量)

    EXCEL的列:组织id,供应商编号,供应商地点,料号,最小拆分量.采购提前期.最小订购量.最小包装量 --采购导入更新MOQ四个值,若有为空的那列,会保留原来的值,不会去更新那列的值 PROCEDU ...

  8. 漫谈Word2vec之skip-gram模型

    https://zhuanlan.zhihu.com/p/30302498 陈运文 ​ 复旦大学 计算机应用技术博士 40 人赞同了该文章 [作者] 刘书龙,现任达观数据技术部工程师,兴趣方向主要为自 ...

  9. 使用Auto Layout中的VFL(Visual format language)——代码实现自动布局

    本文将通过简单的UI来说明如何用VFL来实现自动布局.在自动布局的时候避免不了使用代码来加以优化以及根据内容来实现不同的UI. 一:api介绍 1.NSLayoutConstraint API NSL ...

  10. 牛客网数据库SQL实战 1-11

    1. 查找最晚入职员工的所有信息 CREATE TABLE `employees` ( `emp_no` ) NOT NULL, `birth_date` date NOT NULL, `first_ ...