- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章C/C++中指针和引用之相关问题深入研究由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
1、基本知识 指针和引用的声明方式: 声明指针: char* pc; 声明引用: char c = 'A' char& rc = c,
它们的区别: ①从现象上看,指针在运行时可以改变其所指向的值,而引用一旦和某个对象绑定后就不再改变。这句话可以理解为:指针可以被重新赋值以指向另一个不同的对象。但是引用则总是指向在初始化时被指定的对象,以后不能改变,但是指定的对象其内容可以改变.
②从内存分配上看,程序为指针变量分配内存区域,而不为引用分配内存区域,因为引用声明时必须初始化,从而指向一个已经存在的对象。引用不能指向空值.
③从编译上看,程序在编译时分别将指针和引用添加到符号表上,符号表上记录的是变量名及变量所对应地址。指针变量在符号表上对应的地址值为指针变量的地址值,而引用在符号表上对应的地址值为引用对象的地址值。符号表生成后就不会再改,因此指针可以改变指向的对象(指针变量中的值可以改),而引用对象不能改。这是使用指针不安全而使用引用安全的主要原因。从某种意义上来说引用可以被认为是不能改变的指针.
④不存在指向空值的引用这个事实意味着使用引用的代码效率比使用指针的要高。因为在使用引用之前不需要测试它的合法性。相反,指针则应该总是被测试,防止其为空.
⑤理论上,对于指针的级数没有限制,但是引用只能是一级.
如下:
注意上述读法是从左到右。 程序1:
程序2:
可以认为: 引用就是变量的别名,在引用初始化的时候就已经确定,以后不能再改变。见程序2的粗体字语句。第1句,声明了rs引用s1,s1的值为”Hello”,从这以后,rs实际上就相当于变量s1了,或者从更本质的意义上来说,rs的地址就是初始化时s1的地址了,以后都不会再改变。这应该比较好理解,比如我们在程序中定义了一个变量a,不管我们如何给a赋值,但它的地址是不会改变的; 第2句,rs仍旧指向初始化时s1的地址,但此处的赋值就相当于重新给s1赋值,因此我们从第3句和第4句可以看到,s1的地址并没有发生变化,但是其值已经发生了变化.
。
2、作为参数传递 利用引用的这个特性,可以用它作为函数的传出参数。如程序3:
而一般变量,则不能从函数内部传值出来,比如程序4:
当然程序3引用传递的方式也可以写成指针传递的方式,如程序5:
注意程序中的陷井,如程序6:
这段程序先调用了SomeFunction函数,创建了个叫nNumber的变量,接着让指针pPointer指向了它。可是问题出在哪儿呢?当函数结束后,nNumber被删掉了,因为这一个局部变量。局部变量在定义它的函数执行完后都会被系统自动删掉。也就是说当SomeFunction 函数返回主函数main()时,这个变量已经被删掉,但pPointer还指着变量曾经用过的但现在已不属于这个程序的区域。 尽管在SomeFunction中使用所谓的动态分配内存。程序7中也存在陷井:
原因也如上面所言,intNumber的作用范围仅限于SomeFunction中,离开了SomeFunction,那么intNumber就不存在了,那么&intNumber即intNumber的地址就变得没有意义了,因此,该地址所指向的值是不确定的。如果改为下面的程序就不会有问题了.
。
程序8:
3、指针的指针 前面说到,指针是没有级数限制的。 程序9:
输出的结果: 1 2 3 4 5 6 7 8 9 10 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 11 12 13 14 15 16 17 18 19 20 21 22 。
。
4、函数指针和函数引用 函数指针是C++最大的优点之一。和使用普通指针相比,高级程序员只要有可能都更愿意使用引用,因为引用更容易处理一些。然而,当处理函数时,函数引用对比函数指针就未必有这个优势了。现有的代码很少使用函数引用。下面将向介绍如何函数指针、如何使用函数引用以及分别在什么情况下使用它们.
① 函数指针的例子 。
② 函数引用的例子 。
③ 函数指针和函数引用作为函数参数 。
总结: 函数指针的声明使用方式: <想要指向的函数之返回类型>(*函数指针的名称)<想要指向的函数之参数类型…> 如要想声明一个函数指针指向以下函数:
那么就可以如下操作: void (*pFunction)(int); 然后如下用函数的地址给pFunction赋值: pFunction = &print; 在然后,pFunction就可以和函数print一样使用了,比如, pFunction(1); 等等。 函数引用的声明和使用方式: <欲引用的函数之返回类型>(&函数引用的名称)<欲引用的函数之参数类型…>=<欲引用的函数的名称>,至所以如此,是引用在声明的时候必须初始化,引用不能指向空值。 如要想声明一个函数引用指向以下函数:
那么就可以如下操作: void (&rFunction)(int)=print; 在然后,rFunction就可以和函数print一样使用了,比如, rFunction(1); 等等.
。
5、const修饰指针和引用 大致而言,const修饰指针和引用分三种情况,即const修饰指针、const修饰引用和const修饰指针的引用。下面分别讨论之。 ① const修饰指针 const修饰指针又分为三种情况,即const修饰指针本身、const修饰指针所指的变量(或对象)以及const修饰指针本身和指针所指的变量(或对象)。 a. const修饰指针本身 在这种情况下,指针本身是常量,不能改变,任何修改指针本身的行为都是非法的,例如: double pi = 3.1416; double* const PI = π double alpha = 3.14; PI = α // 错误。因为指针PI是常量,不能再被改变。 *PI = alpha; // OK。虽然指针PI不能被改变,但指针所指的变量或者对象可变。 b. const修饰指针指向的变量(或对象) 在这种情况下,指针本身可以改变,但const所修饰的指针所指向的对象不能被改变,例如: double pi = 3.1416; const double* PI = π double alpha = 3.14; *PI = alpha;// 错误。因为PI所指向的内容是常量,因此*PI不能被改变。 PI = α// OK。虽然指针所指的内容不能被改变,但指针PI本身可改变。从而通过这种方式改变*PI.
c. const修饰指针本身和指针所指向的变量(或对象) 在这种情况下,指针本身和指针指向的变量(或对象)均不能被改变,例如: double pi = 3.146; const double* const PI = π //double const* const PI = π cout << "PI = " << PI << endl; cout << "*PI = " << *PI << endl; double alpha = 3.14; //*PI = alpha; // 错误。因为PI所指向的内容是常量,因此*PI不能被改变。 //PI = α // 错误。因为指针PI是常量,不能再被改变。 ② const修饰引用 const修饰引用没有指针修饰指针那么复杂,只有一种形式。引用本身不能被改变,但所指向的对象是可以被改变的,见上面“1、基本知识”。 double pi = 3.1416; //const double& PI = pi; double const& PI = pi; //和上面一句是等价的 //double& const PI = pi;//有问题。很多编译器会产生warning cout << PI << endl; ③ const修饰指针引用 我们用例子来说明。 double pi = 3.14; const double* pPI = π //const double*& rPI = π //错误。不能将double* 转换成const double *& const double*& rPI = pPI; //OK。声明指针引用的正确方法 。
说明:const double*& rPI = π 为什么会出现错误呢?我们知道,引用是被引用对象的别名,正因为如此,由于rPI是pPI的别名,因此rPI和pPI的类型必须完全一致。从上面的代码段我们可以看到,rPI的类型是const double*,而&pi的类型是double*,因此这句程序是错误的。 下面这段代码和 ① 中的b中的情形对应(即内容不可变,指针可变): double pi = 3.1416; double api = 3.14; const double* pPI = π const double* pAPI = &api; const double*& rPI = pPI; const double*& rAPI = pPI,
*rAPI = api; // 错误。指针所指向的值不能被直接改变 rAPI = pAPI; // OK。指针本身可以被改变 。
指针引用的用法还有其它的情形,由于罕用,故此不谈及.
最后此篇关于C/C++中指针和引用之相关问题深入研究的文章就讲到这里了,如果你想了解更多关于C/C++中指针和引用之相关问题深入研究的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
第一段代码工作正常,并给出了我需要的结果。我现在想做的是让它在 'as num' 上返回 3 个数字值对于“as num”上的 3 个不同值,对于同一列上的 3 个不同位置 SELEC
我想分析一些数据以编写定价算法。以下日期可用: 我需要三个变量/维度的函数/相关因子,它显示三个维度(pers_capacity、卧室数量、浴室数量)增长时中位数(价格)的变化。例如Y(#pers_c
正如标题所说 - 我的 Sprite Kit 游戏时不时地在后台崩溃,总是出现此错误 - Exception Type: EXC_BAD_ACCESS (SIGSEGV) Exception Sub
假设我尝试保存以下数据,并且Songs模型的name属性上设置了Phalcon \ Mvc \ Model \ Validator \ PresenceOf验证器 // Get an existing
我有一个 if 控件,如下所示; if (Directory.Exists(System.IO.Path.Combine(systemPath, "Reports", companyName))
有人可以告诉我我们使用 ReadLine() 从文件 (.txt) 中读取特定行吗?现在我想读取文件的全部内容(不仅仅是第一行)。为此我需要使用什么方法。我用谷歌搜索了很多,但找不到解决方案。 我的代
我相信在大学时我用从 C 派生的语言为 FPGA 编写了一个程序。我了解 VHDL 和 verilog 等语言。但是,我不明白的是程序员在使用哪个方面有多少选择?它依赖于FPGA吗?我将使用 Xili
我有一个 if 控件,如下所示; if (Directory.Exists(System.IO.Path.Combine(systemPath, "Reports", companyName))
如何在运行时更改 Dashcode (Javascript) 中图像对象的源? 我试过: var image = document.getElementById("image").object;ima
我有几个相互关联的类,它们将被多种不同的算法使用 例子: struct B; struct A { B* parent; }; struct B { std::vector child
我正在开发一个网站,用户在客户收到的表中输入金额,如果任何客户没有提供分期付款(金额),则用户不会在表中输入任何金额,并且用户希望获取违约者的信息客户以10天为基础。所以我的问题是应该定义什么表和属性
我试图从上一个条目中选择一个值,并每次将该数字加一。我让它工作到选择当前条目值(默认 1000)并递增 1 并重新插入该值(因此每次最终都是 1001)。我需要它来选择该字段的最后一个条目,这样它将变
我不擅长“制作”查询。假设这是我的数据库: artist pics ------------------- -
最近,我要为我的网站做一个即时通知系统。我听说 COMET 在这种情况下必不可少。 我已经搜索 PHP 和 Comet 一段时间了,但是,我发现的指南和文章似乎只是循环中的 ajax 请求。例如,有一
我正在开发一款 iOS 游戏,我希望 clown 在场景外生成,然后向下移动。我的想法是全部创建它们,并将它们以 360 像素的距离放置在不可见的场景中。 像这样: SKSpriteNode *clo
我有以下子订单表。 mysql> select * from suborder; +-------------+------------------+ | order_state | bookin
这可能是一个有点初学者的问题,但考虑到在 Java 中调试编码是相当相关的:什么时候编码与 String 对象相关? 假设我有一个要保存到文件中的字符串对象。 String 对象本身是否使用某种我应该
首先我想说我是 CPP 的新手(我从 cpp11 开始):)考虑以下实体:学生(名字+姓氏)和组(描述+更多学生)。我在 C++ 中创建了以下 2 个类: class Student { privat
我正在尝试在单击该复选框时同步更新我的数据库。我决定使用 aJax,但它似乎无法识别 ajax。 代码:将成为 Switch_Active(this.id) 函数的元素 ... Deactivat
我正在创建一个菜单。菜单如下。 $('.category').mouseover(function() { $(this).removeClass('category').addClass('cate
我是一名优秀的程序员,十分优秀!