C++ 指针和引用 吐血整理 Pointer&Reference
说道C++的指针,很多人都很头疼,也很confuse。经常把它和变量名,引用(reference)等混淆,其实这最主要的原因是很多程序员对于基本知识的掌握有问题,从而导致的很多基本概念的混淆。本文就是从最基本的概念讲起,着重分析和比较指针和引用。主要从以下几个方面着重的讲解:
1. 变量(variable)的表现形式;
2. 指针的结构和原理;
3. 引用的结构和原理;
4. 指针在Array中的应用和注意事项;
5. 指针不能dereference的几种情况;
一:变量的形式
说道变量,很多人都觉得非常简单,每天都在定义变量,应用变量。可是有没有停下脚步细细的品味一下具体什么是变量呢?变量(variable)的定义在计算机科学中到底是如何定义的?然后variable到底是在内存中如何存储值的呢?那么跟着上面的问题,我们来一一的解答,首先最重要的,variable的定义,当你申明一个变量的时候,计算机会将指定的一块内存空间和变量名进行绑定;这个定义很简单,但其实很抽象,例如:int x = 5; 这是一句最简单的变量赋值语句了, 我们常说“x等于5”,其实这种说法是错误的,x仅仅是变量的一个名字而已,它本身不等于任何值的。这条statement的正确翻译应该是:“将5赋值于名字叫做x的内存空间”,其本质是将值5赋值到一块内存空间,而这个内存空间名叫做x。切记:x只是简单的一个别名而已,x不等于任何值。其图示如下:
变量在内存中的操作其实是需要经过2个步骤的:
1)找出与变量名相对应的内存地址。
2)根据找到的地址,取出该地址对应的内存空间里面的值进行操作。
二:指针的结构和原理
首先介绍到底什么是指针?指针变量和任何变量一样,也有变量名,和这个变量名对应的内存空间,只是指针的特殊之处在于:指针变量相对应的内存空间存储的值恰好是某个内存地址。这也是指针变量区别去其他变量的特征之一。例如某个指针的定义如下:
int x = ;
int *ptr = &x;
ptr即是一个指正变量名。通过指针获取这个指针指向的内存中的值称为dereference,这个的中文翻译叫啥我也不知道。【惭愧】,哈哈。dereference
其相对于内存空间的表示如下:
特别提醒:这里千万千万不要钻进变量名x, ptr的牛角尖里面,不要去思考这些变量名存储在哪里,变量名仅仅是一块内存空间的代号名字而已,我们应该关心的是这些变量名相对应的内存地址。根据上面的分析可以看出,指针变量和任何变量在内存中的形式是相同的,仅仅在于其存储的值比较特殊而已。
三:引用在内存中的结构和原理
引用(reference)在C++中也是经常被用到,尤其是在作为函数参数的时候,需要在函数内部修改更新函数外部的值的时候,可以说是引用场景非常丰富。但程序员一般很难或者不注意分析reference和pointer,只是知道怎么应用而已,而不去具体分析这个reference。下面我就来简单的分析一下这个reference。首先我们必须明确的一点就是:reference是一种特殊的pointer。从这可以看出reference在内存中的存储结构应该跟上面的指针是一样的,也是存储的一块内存的地址。例如reference的定义如下:
int x = ;
int &y = x;
reference 和 pointer主要有以下3中不同点:
1)reference不需要dereference即可直接获取到指向的内存空间的值。例如上例中,直接y就可以获取reference y所指向的内存空间的值,而不需要*y来获取。
2)reference的赋值操作也不需要取地址符来赋值,可以直接通过变量名,例如上例中,int &y = x, 而不需要 int &y = &x;
3) reference 在申明的时候就必须要有初始值,而且reference变量指向的内存地址是不能变化,不像pointer那样可以很灵活的重新指向其他地址。
reference和pointer在内存中的结构和关系如下图所示:
四:指针在Array中的应用和注意事项
在C++中,一个Array类型的变量arr, 其实本质是一个指向数组第一个元素的指针。字符串string在C++中其实就是一个char类型的array,例如:char arr[] = {'a','b','c','d','e','\0'};这就是表示的一串字符串“abcde”,其中arr[0],arr[1], arr[2]..........之间相差的数值可能并不一定是1byte, 要根据这个数组的类型来判断,compiler会自动判断它们之间的相差值的; 另外在c++中字符串也可以用string literals(求大神翻译)的方式表示,即:char *arr2 = "abcde"; 但是通过string literal方式表示的字符串是read only的,不能修改的, 例如:*(arr2+1)= 'f'; 这句语句会产生error的。其在内存中的表现形式如下图所示:
五:指针不能dereference的情况
但一个指针的值是invalid的时候,那么这个指针是不能dereference的。那么到底哪几种情况是invalid的呢?主要有以下几种情况:
1)当这个指针的值是NULL的时候,这个指针是不能dereference的。因为指针为NULL,即表示这个指针指向内存地址为0的地址块,内存地址为0的内存空间是没有值的,所以是不能dereference的; 例如:int *ptr = NULL; cout<<*ptr<<endl; 是错误的。
2)当某个指针被deallocte或者某个指针所在的内存空间被erase了的话,那么这个指针也是不能被dereference的;例如下面的代码:
int *function(int a){ int temp = ;
return &temp;
}
上面的代码返回的指针也是不能dereference的,因为temp出了作用域后会被系统回收这一块空间,temp所占的内存空间已经被erase了,所以它返回的指针是一个指向被erase了的内存空间。也是不能dereference的,否则会出错。编译阶段会给出警告,在runtime的时候,如果dereference是会有error的。
好了C++的指针(pointer)和引用(reference)就先总结到这里了。
如果有什么问题欢迎大家的留言或者建议。谢谢
C++ 指针和引用 吐血整理 Pointer&Reference的更多相关文章
- [转]C++ 指针和引用
转自http://www.cnblogs.com/tangxiaobo199181/ 作者:算法生活 微信公众号:算法生活 出处:http://www.cnblogs.com/tangxiaobo19 ...
- 【转】 BSS段 数据段 代码段 堆栈 指针 vs 引用
原文:http://blog.csdn.net/godspirits/article/details/2953721 BSS段 数据段 代码段 堆栈 (转+) 声明:大部分来自于维基百科,自由的百科全 ...
- C++指针与引用
1.指针与引用的区别: (1)非空区别.引用不能指向空值. (2)合法性区别.由于指针可能为空,所以需要测试它以防止它为空. (3)可修改区别.引用初始化后不可再被修改. (4)内容区别.指针的内容是 ...
- 【C++】指针和引用
引用: 引用(reference)是为对象起了另外一个名字,引用类型应用(refers to)另外一种类型.通过将声明符写成&d的形式来定义引用类型,其中d是声明的变量名. 一般初始化变量时, ...
- 指针和引用在C++中应用
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...
- 在C++中指针和引用传值区别
笔者介绍:姜雪伟,IT公司技术合伙人,IT高级讲师,CSDN社区专家,特邀编辑,畅销书作者,已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D实战核心技术详解 ...
- 对比 C++ 和 Python,谈谈指针与引用
花下猫语:本文是学习群内 樱雨楼 小姐姐的投稿.之前已发布过她的一篇作品<当谈论迭代器时,我谈些什么?>,大受好评.本文依然是对比 C++ 与 Python,来探讨编程语言中极其重要的概念 ...
- 指针 vs 引用 (2)
这波要针对上篇分析里 标红的问题(成员变量用 T,T&啥情况)继续思考, 要学习以下材料: 1. 知乎上:用指针还是引用 2. StackOverflow上的相关问题 https://stac ...
- C++_系列自学课程_第_8_课_指针和引用_《C++ Primer 第四版》
C语言最富有迷幻色彩的部分当属指针部分,无论是指针的定义还是指针的意义都可算是C语言中最复杂的内容.指针不但提供给了程序员直接操作硬件部分的操作接口,还提供给了程序员更多灵活的用法.C++继承这一高效 ...
随机推荐
- Linux.挖矿.cpuminer方法记录
挖矿一般都要用高端显卡做矿机, 不是一般人玩得起 这里讲的是一种用CPU来挖矿的方法, 纯玩玩, 不要指望能致富喔 本方法在CentOS和树莓派原生系统上测试通过 先从git下载cpuminer gi ...
- LeetCode 120. Triangle (三角形)
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent n ...
- LeetCode 62. Unique Paths(所有不同的路径)
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...
- macOs升级到10.13.1Beta || JAVA升级到最新版之后PhpStorm菜单栏问题
macOs升级到10.13.1Beta || JAVA升级到最新版之后PhpStorm菜单栏会消失,估计不止出现在PhpStorm,一系列jetbrains的产品可能都会有这个问题,包括eclipis ...
- Java中Double保留后小数位的几种方法
最近做个小实验,其中一部分要求将表单提交的数据转换为double,这个功能其实很简单直接一句Double.parseDouble(request.getParameter("chinese& ...
- C#设计模式之十一外观模式(Facade)【结构型】
一.引言 快12点半了,要开始今天的写作了.很快,转眼设计模式已经写了十个了,今天我们要讲[结构型]设计模式的第五个模式,该模式是[外观模式],英文名称是:Facade Pattern.我们先从名字上 ...
- angular指令之complie和link不得不说的故事
angular指令比较晦涩难懂的就是complie和link字段了,什么时候该用complie?什么时候该用link?总是很难分别清楚.当理解了指令的真正编译原理的时候,就会发现这相当的简单. ng怎 ...
- 哈尔滨理工大学第六届程序设计团队 E-Mod
/* 成功水过,哈哈哈,可能数据水吧 */ #include <stdio.h> #include <algorithm> #include <string.h> ...
- 【Tesseract】Tesseract 的训练流程
在泰迪杯A题中,我刚刚接触了Tesseact,其中训练字库中遇到了较多的问题.所以在此记录一下,也当做一个笔记,省得以后忘记. 为了方便 ,将tif命名格式设为[lang].[fontname].ex ...
- riot.js教程【三】访问DOM元素、使用jquery、mount输入参数、riotjs标签的生命周期
前文回顾 riot.js教程[二]组件撰写准则.预处理器.标签样式和装配方法 riot.js教程[一]简介 访问DOM元素 你可以通过this.refs对象访问dom元素 而且还有大量的属性简写方式可 ...