C++指针与引用(Pointers OR References)
一、Pointers
Pointer是指针,可以用来指向任何一个objects,包括一般变量:
1 int i = 3;
2 int * pi = &i;
3 cout << pi << endl; // 0x0064FDF0
4 cout << *pi << endl; // 3
此时pi本身内含i的地址,要取出pi所指向的object,可以使用*运算符(dereference operator).Pointer也可以用来指向任何一个class type objects。由于下面的pPoint指向一整个大结构(一个object),如果要取用其中的members(data members 或member functions都可以,只要他们的封装等级是public),必须使用—>运算符(arrow operator),例如:
1 class CPoint { public: float _x, _y, _z; };
2 CPoint * pPoint = new CPoint;
3 cout << pPoint << endl; // 0x00770560
4 pPoint->_x = 9.28;
5 cout << pPoint->_x << endl; // 9.28
Pointer 甚至可以指向一个不明对象(void):
1 void * pv;
2 pv = malloc(1024); // 配置 1024 bytes(来自 heap)
3 cout << pv << endl; // 0x00760A14
此时如果要提取 pv 所指的对象,不可以,会出现编译出错:
1 cout << *pv << endl; // error C2100: illegal indirection
也说是说,pointer本身没有意义,它的意义来自于它的类型,因此,将pointer前进一个单位,究竟是前进多少个bytes呢?那要看pointer的类型,如果将int *pi和CPoint *pPoint各加1,得到:
1 cout << ++pi << endl; // 0x0064FDF4,比原先增加 4
2 cout << ++pPoint << endl; // 0x0077056C,比原先增加 12
这是因为在32位的系统中int为4 bytes,而我们设计的CPoint里面有一个float数据,大小为12bytes,所以各指针累加1时,分别前进4bytes和12bytes。如果把一个指向不明对象的指针加1,会得到什么结果呢?不会有结果,只会编译出错:
1 cout << ++pv << endl; // error C2036: 'void *' : unknown size
当然,如果你做了强转型(cast)动作,就可以解决“不明对象”的问题,因为你赋予了该指针一个明确的类型,例如:
1 double * pd = (double*)pv; // 强转型。double is 8 bytes.
2 cout << pd << endl; // 0x00760A14
3 cout << ++pd << endl; // 0x00760A1C,比原先增加 8
下表是上述验证结果的一个整理:

当我们开始设计classes继承体系,有许多时候需要把一个pointer指向一个类型不符的object(但彼此类型又有继承的关系存在,这其实正是polymorphism的一个精髓),这时候类型的转换就非常重要。强制转型太过粗暴,在不够安全的时候仍然强转换,存在风险。C++有其它更精致的转型工具,我们后续再谈。
Pointer不但可以指向object,还可以指向class的data members或member functions。它们的形式有点怪,结果也可能出人意外,这些问题我们后续再谈。
二、References
与pointer常常相提并论,并且常常被混淆不清的是所谓的reference。Reference(&)像是一个常数指针,可以被自动提取(dereference)。下面这个例子就是使r成为x的一个reference:
1 int x;
2 int& r = x; // r is a reference of x
当一个refernce产生,它必须被初始化为某个原已存在的object,像上面那样,如查我写:
1 int& q = 12;
那么编译器会先配置一块int内存空间,将内容设为12,然后把q这个reference“捆绑”到该空间上。重点是,任何reference都必须被“捆绑”到某一个空间,成为一个"化身“。当你处理该reference,你就是在处理那个被捆绑的空间。如果:
1 int x = 0;
2 int& r = x; // r is a reference of x
3 int* p = &x; // p is a pointer to x
4 r++; // 请注意:sizeof(r) == sizeof(x)
那么r和x的现值都为1,因为增加r的值就是增加x 的值。

面对reference,最简单的想像就是,把它幻想为一个形式漂亮的pointer。这个形式漂亮的pointer好处是,我们不需要担心它是否被初始化(编译器会强迫做),也需要担心何提取(dereference)它(同样的,编译器会负责)。Refernce虽然在本质上是一个指针,在形式却是个object。也就是因为其形式漂亮,而本质实用(用于call by refernce),所以refernce常被用于函数的参数列表(arguments list)和回传值(return value)。下面就是个例子:
1 int* funcl(int* x)
2 {
3 (*x)++;
4 return x;
5 }
6
7 int& func2(int& x)
8 {
9 x++;
10 return x;
11 }
12
13 int main()
14 {
15 int a=0;
16 //ugly but explictit,你可以你可以清楚看到传給 func1() 的是个指针。
17 //传回值的形式也很「难看」。
18 cout<<*funcl(&a)<<endl;
19 // clean but hidden。传給 func2() 的其实是个指针(借助 reference)。
20 // 但你看不出來。传回的也是指针(借助 reference),你也看不出來。
21 cout<<func2(a)<<endl;
22 23 return 0;
24 }
C++指针与引用(Pointers OR References)的更多相关文章
- golang 中Pointers Vs References
原文: https://spf13.com/post/go-pointers-vs-references/ Pointers Vs References Some languages includin ...
- C++指针与引用
1.指针与引用的区别: (1)非空区别.引用不能指向空值. (2)合法性区别.由于指针可能为空,所以需要测试它以防止它为空. (3)可修改区别.引用初始化后不可再被修改. (4)内容区别.指针的内容是 ...
- C/C++中指针和引用之相关问题研究
一.基本知识 指针和引用的声明方式: 声明指针: char* pc; 声明引用: char c = 'A' char& rc = c; 它们的区别: ①从现 ...
- [速记]关于指针,引用和递归和解递归——C++
在写基于二叉排序树的查找时,分为三个过程 1.二叉排序树的插入 2.二叉排序树的建立 3.基于二叉排序树的查找 其中第三部可以递归方式实现,也可以用while循环解递归,于是我想也解解第一步的递归,看 ...
- C++指针参数引用
粘个代码占位置,以后有时间把指针函数,函数指针都补上 #include <iostream> using namespace std; void freePtr1(int* p1){ /* ...
- C/C++:提升_指针的指针和指针的引用
C/C++:提升_指针的指针和指针的引用 写在前面 今天在使用指针的时候我发现了一个自己的错误.
- C++_系列自学课程_第_8_课_指针和引用_《C++ Primer 第四版》
C语言最富有迷幻色彩的部分当属指针部分,无论是指针的定义还是指针的意义都可算是C语言中最复杂的内容.指针不但提供给了程序员直接操作硬件部分的操作接口,还提供给了程序员更多灵活的用法.C++继承这一高效 ...
- C++学习笔记 指针与引用
指针与引用 1. 指针 (1) 指针是一个变量(实体),存储的是一个地址,指向内存的一个存储单元,指针可以为空 (2) 指针可以为空,在声明定义时可以不初始化 (3) 指针在初始化之后可以重新指向其 ...
- 数组类型与sizeof与指针的引用
以char类型为例: char a[100]; //a类型为char[100] &a类型为 char (*)[100] *a类型为char char *p = a; ...
- c++指针与引用问题
本来是回答问题的,到这里做个笔记 *&L是指针的引用,实参是个指针.所以L是实参指针的别名,对别名L的修改,等于对实参的修改.*L是传值,你无法改变传过来的实参指针变量的值程序代码: #inc ...
随机推荐
- Bad magic number for central directory
Bad magic number for central directory 运行代码输出如下bug: File "/home/a/Prediction/Predict_Models.py& ...
- DevOps迈向标准化,平台工程让开发运维更轻松
在近一代人的时间里,DevOps 在软件开发和运维领域占据了主导地位.这是一套开发人员都离不开的技能和方法.Pearl Zhu 在 "The Digital Master" 一书中 ...
- KingbaseES Json 系列四:Json数据操作函数二
KingbaseES Json 系列四--Json数据操作函数二(JSONB_PRETTY,JSONB_STRIP_NULLS,JSON_OBJECTAGG,JSON_EQUAL,JSON_EXIST ...
- Android弹出UI界面---Toast
1.默认展示 1 // 第一个参数:当前的上下文环境.可用getApplicationContext()或this 2 // 第二个参数:要显示的字符串.也可是R.string中字符串ID 3 // ...
- 【FAQ】HarmonyOS SDK 闭源开放能力 —Push Kit(3)
1.问题描述: 调用HarmonyOS API发送通知,能查到状态是送达终端设备,但是终端设备上没收到通知卡片. 解决方案: 通知应用大图标不能超过30kb,通知参数限制,参考如下:https://g ...
- 实例讲解昇腾 CANN YOLOV8 和 YOLOV9 适配
本文分享自华为云社区<昇腾 CANN YOLOV8 和 YOLOV9 适配>,作者:jackwangcumt. 1 概述 华为昇腾 CANN YOLOV8 推理示例 C++样例 , 是基于 ...
- HarmonyOS崩溃服务能力全新上线,帮你高效解决崩溃问题!
原文:https://mp.weixin.qq.com/s/YmYzNXsvsqt8U8JX3vlmrg,点击链接查看更多技术内容. 一.为什么需要崩溃服务能力 用户在使用原子化服务时,出现卡顿.缓慢 ...
- RestfulApi 学习笔记——.net core入门操作(二)
前言 前面简单介绍了一下restfulapi是什么东西,那么我们应该在.net core 中如何实现呢?或者说该怎么做才能有这个restful api呢? 正文 幸运的是.net core帮助我们实现 ...
- 介绍一个气缸控制的FB程序块
关键词: 气缸,双控.单控.电磁阀.感应器.初始位置(简称"始位").末端位置(简称"端位").屏蔽功能.延时功能.报警功能 正文: 1.为什么要做气缸FB功能 ...
- 力扣396(java)-旋转数组(中等)
题目: 给定一个长度为 n 的整数数组 nums . 假设 arrk 是数组 nums 顺时针旋转 k 个位置后的数组,我们定义 nums 的 旋转函数 F 为: F(k) = 0 * arrk[0 ...