转自http://www.cnblogs.com/tangxiaobo199181/

作者:算法生活

微信公众号:算法生活

出处:http://www.cnblogs.com/tangxiaobo199181/

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

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 = 5;
int *ptr = &x;

ptr即是一个指正变量名。通过指针获取这个指针指向的内存中的值称为dereference,这个的中文翻译叫啥我也不知道。【惭愧】,哈哈。dereference

其相对于内存空间的表示如下:



特别提醒:这里千万千万不要钻进变量名x, ptr的牛角尖里面,不要去思考这些变量名存储在哪里,变量名仅仅是一块内存空间的代号名字而已,我们应该关心的是这些变量名相对应的内存地址。根据上面的分析可以看出,指针变量和任何变量在内存中的形式是相同的,仅仅在于其存储的值比较特殊而已。

三:引用在内存中的结构和原理

引用(reference)在C++中也是经常被用到,尤其是在作为函数参数的时候,需要在函数内部修改更新函数外部的值的时候,可以说是引用场景非常丰富。但程序员一般很难或者不注意分析reference和pointer,只是知道怎么应用而已,而不去具体分析这个reference。下面我就来简单的分析一下这个reference。首先我们必须明确的一点就是:reference是一种特殊的pointer。从这可以看出reference在内存中的存储结构应该跟上面的指针是一样的,也是存储的一块内存的地址。例如reference的定义如下:

int x = 5;
int &y = x;

reference 和 pointer主要有以下3中不同点:

1)reference不需要dereference即可直接获取到指向的内存空间的值。例如上例中,直接y就可以获取reference y所指向的内存空间的值,而不需要*y来获取。

2)reference的赋值操作也不需要取地址符来赋值,可以直接通过变量名,例如上例中,int &y = x, 而不需要 int &y = &x;

  1. 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 = 5;
return &temp;
}

上面的代码返回的指针也是不能dereference的,因为temp出了作用域后会被系统回收这一块空间,temp所占的内存空间已经被erase了,所以它返回的指针是一个指向被erase了的内存空间。也是不能dereference的,否则会出错。编译阶段会给出警告,在runtime的时候,如果dereference是会有error的。

好了C++的指针(pointer)和引用(reference)就先总结到这里了。

作者:算法生活

微信公众号:算法生活

出处:http://www.cnblogs.com/tangxiaobo199181/

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.

[转]C++ 指针和引用的更多相关文章

  1. [速记]关于指针,引用和递归和解递归——C++

    在写基于二叉排序树的查找时,分为三个过程 1.二叉排序树的插入 2.二叉排序树的建立 3.基于二叉排序树的查找 其中第三部可以递归方式实现,也可以用while循环解递归,于是我想也解解第一步的递归,看 ...

  2. C++指针参数引用

    粘个代码占位置,以后有时间把指针函数,函数指针都补上 #include <iostream> using namespace std; void freePtr1(int* p1){ /* ...

  3. C/C++:提升_指针的指针和指针的引用

    C/C++:提升_指针的指针和指针的引用 写在前面 今天在使用指针的时候我发现了一个自己的错误.

  4. C++_系列自学课程_第_8_课_指针和引用_《C++ Primer 第四版》

    C语言最富有迷幻色彩的部分当属指针部分,无论是指针的定义还是指针的意义都可算是C语言中最复杂的内容.指针不但提供给了程序员直接操作硬件部分的操作接口,还提供给了程序员更多灵活的用法.C++继承这一高效 ...

  5. C++学习笔记 指针与引用

    指针与引用  1. 指针 (1) 指针是一个变量(实体),存储的是一个地址,指向内存的一个存储单元,指针可以为空 (2) 指针可以为空,在声明定义时可以不初始化 (3) 指针在初始化之后可以重新指向其 ...

  6. 数组类型与sizeof与指针的引用

    以char类型为例: char a[100];     //a类型为char[100]    &a类型为 char (*)[100]    *a类型为char char *p = a;     ...

  7. c++指针与引用问题

    本来是回答问题的,到这里做个笔记 *&L是指针的引用,实参是个指针.所以L是实参指针的别名,对别名L的修改,等于对实参的修改.*L是传值,你无法改变传过来的实参指针变量的值程序代码: #inc ...

  8. C++ 中指针与引用的区别

    指向不同类型的指针的区别在于指针类型可以知道编译器解释某个特定地址(指针指向的地址)中的内存内容及大小,而void*指针则只表示一个内存地址,编译器不能通过该指针所指向对象的类型和大小,因此想要通过v ...

  9. 详解c++指针的指针和指针的引用

    展示一下使用指针的指针和指针的引用修改传递给方法的指针,以便更好的使用它.(这里说的指针的指针不是一个二维数组) 为什么需要使用它们 当我们把一个指针做为参数传一个方法时,其实是把指针的复本传递给了方 ...

  10. 指针和引用的区别(c/c++)

      http://blog.csdn.net/thisispan/article/details/7456169 ★ 相同点: 1. 都是地址的概念: 指针指向一块内存,它的内容是所指内存的地址:引用 ...

随机推荐

  1. LCA(最近公共祖先)——离线 Tarjan 算法

    tarjan算法的步骤是(当dfs到节点u时):1 在并查集中建立仅有u的集合,设置该集合的祖先为u1 对u的每个孩子v:   1.1 tarjan之   1.2 合并v到父节点u的集合,确保集合的祖 ...

  2. java面向对象课程设计-数学表达式计算器

    项目简介 设计一个计算器,其能够: 1)由用户输入一个简单的四则运算表达式,求出其计算结果后显示. 2)特殊数学函数,如:绝对值.取整.三角函数.倒数.平方根.平方.立方等. 3)对一定范围内的数字将 ...

  3. PHPExcel 导出包含图片excel

    <?php // 这里用的PHPExcel版本号为1.8.0 // 下载地址https://github.com/PHPOffice/PHPExcel 下载ZIP压缩包 // 下载后将Class ...

  4. document.querySelector()和document.querySelectorAll()

    HTML5向Web API新引入了 document.querySelector()和document.querySelectorAll()两个方法,都可以接收三种类型的参数:id(#),class( ...

  5. QThread中的互斥、读写锁、信号量、条件变量

    该文出自:http://www.civilnet.cn/bbs/browse.php?topicno=78431 在gemfield的<从pthread到QThread>一文中我们了解了线 ...

  6. BZOJ4513 SDOI2016储能表(数位dp)

    如果n.m.k都是2的幂次方,答案非常好统计.于是容易想到数位dp,考虑每一位是否卡限制即可,即设f[i][0/1][0/1][0/1]为第i位是/否卡n.m.k的限制时,之前的位的总贡献:g[i][ ...

  7. [CF15C]Industrial Nim

    题目大意:有$n$个采石场,每行一个$m_i$一个$x_i$,表示第$i$个采石场有$m_i$辆车,这个采石场中车中的石子为从$x_i$开始的自然数.Nim游戏若先手赢输出"tolik&qu ...

  8. BZOJ 3224 Tyvj 1728 普通平衡树 | Splay 板子+SPlay详细讲解

    下面给出Splay的实现方法(复杂度证明什么的知道是 nlogn 就可以啦) 首先对于一颗可爱的二叉查找树,是不能保证最坏nlogn的复杂度(可以想象把一个升序序列插入) (二叉查找树保证左子树元素大 ...

  9. BZOJ4869 [Shoi2017]相逢是问候 【扩展欧拉定理 + 线段树】

    题目链接 BZOJ4869 题解 这题调得我怀疑人生,,结果就是因为某些地方\(sb\)地忘了取模 前置题目:BZOJ3884 扩展欧拉定理: \[c^a \equiv c^{a \mod \varp ...

  10. shell编程---变量赋值

    echo $filen | awk -F. '{print $3}'  怎么把上边这行脚本产生的字串赋给一个变量啊,实际上会产生一个数, 这个变量用来存这个数.格式应该是怎么写的? a=`echo $ ...