再探C++Primer (4)指针、引用、对象和内存
2016-07-07 00:00
309 查看
摘要: 我曾经是一个用Pascal语言的人,所以刚开始接触C++的时候对于它的指针非常及其的不理解,习惯使用变量而不是指针,不过当真正理解了指针的作用后,却深深的觉得指针实乃神器,是其他任何语言都比不了的。
###基本内置类型和复合类型#
基本内置类型就是算数类型和空类型,算数类型包括字符、整数、布尔值、浮点数,空类型是void;
复合类型指基于其他类型定义的类型,例如指针和引用。
###引用#
引用就是给对象起的别名,通过声明对象时在对象标识符前加‘&’符号来定义引用类型。例如:int a=100;int &b=a;则可以通过对b的操作来操作变量a;
引用本身并不是对象,只是对象的别名,在内存中没有具体的存在;
引用只与其初始化的对象绑定在一起,初始化后不能将引用绑定到其他对象上;
引用只能绑定在对象上而不能绑定在表达式或字面值常量上。
###指针#
指针同引用近似,提供了对其他对象的间接访问;
指针是一个独立的对象,允许对指针进行赋值和拷贝,定义指针后,根据计算机位数不同在内存中占据不同的大小,例如32位计算机/32位编译器中,指针大小是4字节;
指针存储的是对象在内存中的逻辑地址;
指针可以不被初始化也可以在生命周期内指向多个对象。
####获取对象地址、利用指针访问对象#
指针一般要求指针类型同其所指对象严格匹配
指针可以不被初始化,通过取地址符&可以获取对象地址,通过解引用符*可以获取指针所指对象。
####指针值及一些好习惯#
指针值有四种类型:
指向一个对象
指向紧邻对象所占空间的下一个位置
空指针,没有指向任何对象
无效指针,没有指向有效对象
注意:无效指针不等于空指针,无效指针指向了一个未知的位置,而空指针为0值,所以
将输出为1。
试图以任何方式访问无效指针都引发错误,编译器不负责检查此类错误,无效指针导致了大多数令我们痛苦的bug和问题,所以应该养成初始化指针的好习惯。
如果无法确定指针的初值,那么应该让他们等于0或者NULL或者nullptr。
###对象和内存#
在C++中有以下5个内存分配区域:
栈。栈就是编译器需要时分配,不需要时自动清理的变量的存储区,这些变量通常是局部变量、函数参数、临时变量等;
堆。堆就是由我们new 出的对象的存储区,编译器不管他们的释放,所以通常一个new 对应一个delete,如果程序员没有释放掉,那么程序结束后操作系统自动回收。
自由存储区。通过malloc 等分配的内存,他们和堆类似,但是使用free 来结束声明并释放;
全局/静态存储区,全局变量 和静态变量 的存储区;
常量存储区。顾名思义,存放常量 且不允许修改。
关于堆和栈的内容,属于数据结构方面的,栈是一种先进先出的线性表,堆是一种树形结构。
####内存泄漏和野指针#
内存泄漏
主要是指堆和自由存储区内存泄漏,通常由于new或者是malloc之后没有delete或free掉,导致申请的对象空间在使用完毕后依然停留在内存中,特别是在局部new出的变量,由于局部指针在脱离其作用域后已经失效,而申请的空间没有释放导致再也无法释放,就是内存泄漏。
内存泄漏会占用内存空间,降低程序运行效率,特别是当内存泄漏的操作存在于高频率执行的环境下,例如循环体或者递归中,那么系统内存消耗将不断增加,直到最终因没有可分配内存而崩溃。
野指针
是指两种情况:
指针没有初始化;
指针被free或delete后,没有被置为0或NULL或nullptr.
野指针被使用后,由于编译器不会检查此类错误,所以往往容易造成我们难以发现和理解的错误,所以
应该对指针进行初始化;
在free或delete指针后,将其置为nullptr或NULL或0;
不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放.
###基本内置类型和复合类型#
基本内置类型就是算数类型和空类型,算数类型包括字符、整数、布尔值、浮点数,空类型是void;
复合类型指基于其他类型定义的类型,例如指针和引用。
###引用#
引用就是给对象起的别名,通过声明对象时在对象标识符前加‘&’符号来定义引用类型。例如:int a=100;int &b=a;则可以通过对b的操作来操作变量a;
引用本身并不是对象,只是对象的别名,在内存中没有具体的存在;
引用只与其初始化的对象绑定在一起,初始化后不能将引用绑定到其他对象上;
引用只能绑定在对象上而不能绑定在表达式或字面值常量上。
###指针#
指针同引用近似,提供了对其他对象的间接访问;
指针是一个独立的对象,允许对指针进行赋值和拷贝,定义指针后,根据计算机位数不同在内存中占据不同的大小,例如32位计算机/32位编译器中,指针大小是4字节;
指针存储的是对象在内存中的逻辑地址;
指针可以不被初始化也可以在生命周期内指向多个对象。
####获取对象地址、利用指针访问对象#
指针一般要求指针类型同其所指对象严格匹配
int a = 10; int *b; b = &a; //通过取地址符获取变量a地址 int c = *b; //通过解引用符获取指针b所指变量 double *d = a; //错误,指针类型同所指对象不匹配
指针可以不被初始化,通过取地址符&可以获取对象地址,通过解引用符*可以获取指针所指对象。
####指针值及一些好习惯#
指针值有四种类型:
指向一个对象
指向紧邻对象所占空间的下一个位置
空指针,没有指向任何对象
无效指针,没有指向有效对象
注意:无效指针不等于空指针,无效指针指向了一个未知的位置,而空指针为0值,所以
int *a; if (a) std::cout<<'1'<<endl; else std::cout<<'0'<<endl;
将输出为1。
试图以任何方式访问无效指针都引发错误,编译器不负责检查此类错误,无效指针导致了大多数令我们痛苦的bug和问题,所以应该养成初始化指针的好习惯。
如果无法确定指针的初值,那么应该让他们等于0或者NULL或者nullptr。
###对象和内存#
在C++中有以下5个内存分配区域:
栈。栈就是编译器需要时分配,不需要时自动清理的变量的存储区,这些变量通常是局部变量、函数参数、临时变量等;
堆。堆就是由我们new 出的对象的存储区,编译器不管他们的释放,所以通常一个new 对应一个delete,如果程序员没有释放掉,那么程序结束后操作系统自动回收。
自由存储区。通过malloc 等分配的内存,他们和堆类似,但是使用free 来结束声明并释放;
全局/静态存储区,全局变量 和静态变量 的存储区;
常量存储区。顾名思义,存放常量 且不允许修改。
关于堆和栈的内容,属于数据结构方面的,栈是一种先进先出的线性表,堆是一种树形结构。
####内存泄漏和野指针#
内存泄漏
主要是指堆和自由存储区内存泄漏,通常由于new或者是malloc之后没有delete或free掉,导致申请的对象空间在使用完毕后依然停留在内存中,特别是在局部new出的变量,由于局部指针在脱离其作用域后已经失效,而申请的空间没有释放导致再也无法释放,就是内存泄漏。
内存泄漏会占用内存空间,降低程序运行效率,特别是当内存泄漏的操作存在于高频率执行的环境下,例如循环体或者递归中,那么系统内存消耗将不断增加,直到最终因没有可分配内存而崩溃。
野指针
是指两种情况:
指针没有初始化;
指针被free或delete后,没有被置为0或NULL或nullptr.
野指针被使用后,由于编译器不会检查此类错误,所以往往容易造成我们难以发现和理解的错误,所以
应该对指针进行初始化;
在free或delete指针后,将其置为nullptr或NULL或0;
不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放.
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Erlang项目内存泄漏分析方法
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C# Pointer指针应用实例简述
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C和指针小结(推荐)
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法