c++中引用及指针详解
这里写目录标题
- 1、指针
- 1.1、什么是指针
- 指针的本质
- 指针与地址
- 程序中如何声明指针以及如何使用运算符&和*
- 1.2、指针有什么作用
- 指针与函数参数
- 2、引用
- 2.1、什么是引用
- 2.2、引用的规则
- 2.3、引用和数组
- 引用的数组(非法)
- 数组的引用
- 2.4、为什么要用引用
- 3、const修饰符
- 3.1、指针与const
- 3.2、引用与const
- 3.3、指针的引用与const 的关系
1、指针
1.1、什么是指针
指针的本质
通俗来说 指针是一个变量 (保存变量地址的变量)像常见的:
int a=10;
指针与地址
首先 ,我们通过一个简单 的示意图来说明内存是如何组织的。通常机器都有一系列连续编号或编制的存储单元,这些存储单元可以单个进行操作,也可以连续成组的方式操纵。可以这样理解假定一个存储单元是学校的一个宿舍,每个宿舍都会有自己的门牌号,把宿舍楼当做电脑的存储区,想找的一个人,有两种方式(1)直接叫名字(2)直接找到宿舍对应的床位;
通常情况下,机器的一个字节可以存放一个char类型的数据,两个相邻的字节存储单元可存储一个short (短整型)一个long (长整型)组存储单元(通常是2或4个字节)。因此,如果c的类型是char,并且p是指向c的指针,则可用图1.1表示它们之间的关系。
那么一元运算符&可用于取一个对象的地址:
p=&c;
将把c的地址赋值给变量p,我们称p为“指向”c的指针。地址运算符&只能应用于内存中的对象,即变量与数组元素。它不能作用于表达式、常量或register类型的变量。
程序中如何声明指针以及如何使用运算符&和*
int x=1,y=2,z[10];
int *ip;//ip是指向int类型的指针
ip=&x;//ip指向x
y=*ip;//修改y的值为1
*ip=0;//x的值为0
ip=&z[0]//ip指向z[0]
1.2、指针有什么作用
指针与函数参数
由于C语言是以传值的方式将参数值传递给被调用函数的,因此,被调用函数不能直接修改主调函数中变量的值。例如,排序函数可能会使用一个名为swap的函数来交换两个次序颠倒的元素。但是,如果将swap函数定义为下列形式:
void swap(int x, int y)
{int tmp;tmp = x;x = y;y = tmp;
}
int main()
{int a = 10, b = 20;swap(a, b);cout << a << "-----" << b << endl;return 0;
}
结果是:
可以看出 x y的值会被交换 但是主函数 a b的值不会被修改;
那么,如何实现我们的目标呢?可以使主调程序将指向所要交换的变量的指针传递给被
调用函数:
void swap(int *x, int *y)
{int tmp;tmp = *x;*x = *y;*y = tmp;
}
int main()
{int a = 10, b = 20;cout << a << "-----" << b << endl;swap(&a, &b);cout << a << "-----" << b << endl;return 0;
}
调动函数前
调动函数后
指针还有很多,今儿不讨论这些;
2、引用
2.1、什么是引用
可以这样理解 :引用就是别名;举个例子就是猫可以叫猫也可以叫咪咪;
定义一个变量a赋初值为10;并且给a起一个别名为q;
int a=10;
int &q=a;
可以看出其实a和q是同一个东西;
引用的底层实现还是指针;
int &q=a;
等价于
int *const q=&a;
证明一下呗;看图。
2.2、引用的规则
1)&在此不是求地址运算,而是起标识作用。
2)类型标识符是指目标变量的类型。
3)声明引用时,必须同时对其进行初始化。
4)引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。ra=1; 等价于 a=1;
5)声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。故:对引用求地址,就是对目标变量求地址。&ra与&a相等。
6)不能建立数组的引用。因为数组是一个由若干个元素所成的集合,所以无法建立一个数组的别名。
7)不能建立引用的引用,不能建立指向引用的指针。因为引用不是一种数据类型!!所以没有引用的引用,没有引用的指针。
2.3、引用和数组
先看两行代码
int& q[10] ;
//q首先向右结合,所以这个相当于 (int&)q[] q是个数组,其中的元素是引用
//应该叫:引用的数组
int(&p)[10] ;
//p首先和&结合,所以p是引用,引用的对象是数组
//应该叫作数组的引用
眼睛解释的通啊!!!
引用的数组(非法)
可以明确的说明,引用的数组是不能当函数的参数的。再者要说明,这种方式是非法的。
原因:从引用的本质说吧。
首先,引用必须被初始化,而数组并不能被另一个数组初始化或被另一个数组赋值并且因为引用数组的话,就相当于给数组中每个元素引用,没有分配空间。
再次,引用它不支持传统意义的复制,它不占用新的空间。
数组的引用
int main()
{int a[10] = { 10,20,30,40,50,60,70,80,90,100 };// int& q[10] = a;int(&p)[10] = a;for (int i = 0; i < sizeof(a) / sizeof(a[0]); i++){cout << p[i] << " ";}cout << endl;cout << "size=" << sizeof(p) << endl;
}
2.4、为什么要用引用
1)在引用的使用中,单纯给某个变量取个别名是毫无意义的,引用的目的主要用于在函数参数传递中,解决大块数据或对象的传递效率和空间不如意的问题。
2)用引用传递函数的参数,能保证参数传递中不产生副本,提高传递的效率,且通过const的使用,保证了引用传递的安全性。
3)引用与指针的区别是,指针通过某个指针变量指向一个对象后,对它所指向的变量间接操作。程序中使用指针,程序的可读性差;而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
4)使用引用的时机。流操作符<<和>>、赋值操作符=的返回值、拷贝构造函数的参数、赋值操作符=的参数、其它情况都推荐使用引用。 引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样。
3、const修饰符
在C语言中,习惯用#define来定义常量,列如:
#define LIMIT 100
实际上,这种方法只是在预编译阶段进行字符的转换,把程序中出现标识符LIMIT替换为100.在预编译之后,程序不在有LIMIT这个标识符,LIMIT不是变量,没有类型,不占用存储单元,而且容易出错。
C++提供了一种更灵活,更安全的方式来定义常量,即使用const修饰符来定义常量。例如:
const int LIMIT=100;
这个常量是有类型的,占用存储单元,有地址,可以用指针指向它,但不能修改它。
const的作用于#define相似,但是它消除了#define的不安全性。因此c++建议试使用const取代#define定义常量。
说了这么多举个例子呗;
int main()
{int a= 1;#define T1 a+a#define T2 T1-T1cout << "T2 is " << T2 << endl;return 0;
}
想想答案是多少?0还是2?
换一下代码试试
int main()
{int a= 1;int const T1 = a + a;int const T2 = T1 - T1;cout << "T2 is " << T2 << endl;return 0;
}
看下面这两个有区别吗?
实际上没有。
const int a=5;
int const a=5;
const会用了吗?继续。。。
3.1、指针与const
(1)通过指针修改值
int a = 5, b = 10;int* q = &a;*q = 10;
(2)int* const 情况
先搞清楚const限定什么?
int main()
{int a = 10, b = 20;int* const s = &a;s=&b;//错误*s=100;//正确return 0;
}
const限定的是s的指向也就是说s是个常量;即指向不可以改变不能再去只想别的地址,值可以改变。
继续在来,看代码:
int main()
{int a = 10, b = 20;int* const s = &a;int* p1 = s;const int* p2 = s;int* const p3 = s;const int* const p4 = s;return 0;
}
能看出来 那个对那个错吗?
嘿嘿 都对;为什么?
原因就是 s里面存放的是a的地址吧,那也就是说p1他们拿到是a的地址吧,那它有什么错。
(3)const int*
const 限定的是它的值吧即就是*p是个常量吧,和指向没啥子关系;
int main()
{int a = 10, b = 20;const int *p=&a;*p = 100;//错误吧p = &b;return 0;
}
在来看看那个错误:
int main()
{int a = 10, b = 20;const int *s=&a;int* p1 = s;//errconst int* p2 = s;int* const p3 = s;//errconst int* const p4 = s;return 0;
}
p1 p3 错误 原因是 p1指向s的话 p1没有被限定 所以说通过*p1就可以改变a的值,*s的能力被扩大化。
3.2、引用与const
int main()
{int a = 10;int& b = a;const int& c = a;a += 100;b += 100;c+=100;//编译出错,因为前面有const进行修饰,所以c不能改变
}
3.3、指针的引用与const 的关系
(1)int *const
int main()
{int a = 10, b = 20;int* const s = &a;int*& p1 = s;//errconst int*& p2 = s;//errint* const& p3 = s;const int* const& p4 = s;return 0;
}
p1和p2错误的原因一样 就是 s的指向不能修改,而引用就是s的一个别名,所以对p1修改就是对s的修改 s的指向不能被修改但是p1又可以修改 矛盾 ,同是一个东西相煎何太急。。。。
(2)const int *
int main()
{int a = 10, b = 20;const int* s = &a;int*& p1 = s;//errconst int*& p2 = s;int* const& p3 = s;//errconst int* const& p4 = s;}
这个不解释 只要 理解引用是它的别名 也就是修改引用和修改它是同一个操作就行了。
c++中引用及指针详解相关推荐
- C++ 中的this指针详解及实例
C++ 中的this指针详解及实例 这篇文章主要介绍了C++ 中的this指针详解及实例的相关资料,this指针是类的一个自动生成.自动隐蔽的私有成员,它存在于类的非静态成员中,指向被调用函数所在的对 ...
- C语言结构体中定义函数指针详解
C语言结构体中定义函数指针详解 结构体指针函数应用场景之一--驱动程序编写 结构体的一些基本用法 形式1:先定义结构体类型,再定义变量 形式2:在定义类型的同时定义变量 形式3:直接定义变量,用无名结 ...
- c++中的智能指针详解
智能指针是行为类似于指针的类对象,但是这种对象还有其他的功能.一般用于帮助管理动态内存. 我们需要知道,我们每次在对象中new出一块内存空间都需要在对象销毁时delete掉,否则就会造成内存泄露,这些 ...
- C++指针详解(指针初始化与回收,常量与指针,引用与指针)
C++指针详解 1.指针的定义初始化以及回收 2.常量与指针 1)常量指针(常指针) 2)指针常量 3)总结 3.引用与指针 1.指针的定义初始化以及回收 指针是一个地址,这个地址内存放数据,这些数据 ...
- php中 继承中的概念,JavaScript_JavaScript中的继承方式详解,js继承的概念
js里常用的如下 - phpStudy...
JavaScript中的继承方式详解 js继承的概念 js里常用的如下两种继承方式: 原型链继承(对象间的继承) 类式继承(构造函数间的继承) 由于js不像java那样是真正面向对象的语言,js是基于 ...
- C++ 智能指针详解
智能指针内容很多,重点是基本用法. #include <boost/shared_ptr.hpp> class CBase: public boost::enable_shared_fro ...
- c++中vector的用法详解
c++中vector的用法详解 vector(向量): C++中的一种数据结构,确切的说是一个类.它相当于一个动态的数组,当程序员无法知道自己需要的数组的规模多大时,用其来解决问题可以达到最大节约空间 ...
- Python中的高级数据结构详解
这篇文章主要介绍了Python中的高级数据结构详解,本文讲解了Collection.Array.Heapq.Bisect.Weakref.Copy以及Pprint这些数据结构的用法,需要的朋友可以参考 ...
- BAT批处理中的字符串处理详解(字符串截取)
BAT批处理中的字符串处理详解(字符串截取 批处理有着具有非常强大的字符串处理能力,其功能绝不低于C语言里面的字符串函数集.批处理中可实现的字符串处理功能有:截取字符串内容.替换字符串特定字段.合并字 ...
最新文章
- 【设计模式】迭代器模式 ( 简介 | 适用场景 | 优缺点 | 代码示例 )
- 1032 Sharing (25 分) 【难度: 一般 / 知识点: 链表】
- vs2010编译生成后清除obj目录
- 世纪前线网络质量测试工具 是什么_成为一名软件测试工程师有什么前途?
- linux 时间会跳吗,linux系统时间暂时跳跃
- c++ enum 给定类型_在 Rust 中创建 C/C++ API
- JSP — 项目篇《I》【打印九九乘法表】
- 算法4中 1.4节示例中运行次数的讲解
- 抖音网红穿的服装品牌,那些爆款女装号都是怎么拍的呢?
- 今天不了技术,谈情怀,推荐一篇 寒窑赋
- #2991. kiki君的护盾 (shield)
- Android接入谷歌广告 - 发现各种坑
- CWS(美国国土安全部下属的软件保证项目)与SANS(权威安全培训组织)联合编制的最危险的25个编程错误
- 数仓建模—数据治理的本质与实践
- elasticsearch—索引与检索(一)
- WPS格式转换成html代码
- jQuery实现表格导出Excel功能
- 圣思园——Java SE Lesson 6
- 【小程序】中WXML的语法详解
- python中的逻辑量有什么_python小白入门须知的9个基础知识丨纯干货
热门文章
- 2017中国国际纺织面料及辅料(春夏)博览会、2017中国国际纺织纱线(春夏)展览会、2017中国国际家用纺织品及辅料(春夏)博览会会刊(参展商名录)
- 爬取站长之家域名并保存到mysql
- 配置鼠标右键edit with notepad
- 为 Java 程序员准备的 Go 入门 PPT
- 音质出色的降噪旗舰,女毒必选,贝壳王子MO3体验
- 快手用模拟器会被检测吗_欧森杰检测仪:氧气检测仪弄脏了可以用水洗吗?
- 践行新基建,共建城市智能体,为数字经济发展提供新动能
- Project 1:Search in Pacman(吃豆人搜索实验)(一)
- OCR(文字识别)功能与ASR(语音识别)的java应用开发(基于百度智能云)
- chatgpt赋能python:Python是看VIP电影的最佳工具