C++引用的详细解释

目录
  • 一、C++ 引用
    • 1.规则
    • 2.应用
    • 3.引用提高
      • 1.可以定义指针的引用,但不能定义引用的引用。
      • 2.可以定义指针的指针,不能定义引用的指针。
      • 3.可以定义指针数组,但不能定义引用数组,可以定义数组引用。
      • 4.常引用
    • 4.常引用原理
    • 5.const的好处
    • 6.引用的本质浅析
  • 总结

一、C++ 引用

变量名,本身是一段内存的引用,即别名(alias)。此处引入的引用,是为己有变量起一个别名。

声明如下

int main()
{
	int a;
	int &b = a;
}

1.规则

1.引用没有定义,是一种关系型声明。声明它和原有某一变量的关系。类型与原有类型保持一致,且不分配内存。与被引用的变量有相同的地址。

2.声明的时候必须初始化,一经声明,不可变更。

3.可对引用,再次引用。多次引用的结果,是某一个变量具有多个别名。

4.&符号前面有数据类型时,是引用。其他均为取地址。

#include <iostream>
using namespace std;
int main()
{
	int a,b;
	int &r = a;
	int &r = b; //错误,不可更改原有的引用关系
	float &rr = b; //错误,引用类型不匹配
	cout<<&a<<&r<<endl; //变量与引用具有相同的地址。
	int &ra = r; //可对引用更次引用,表示 a 变量有两个别名,分别是 r 和 ra
}

2.应用

1.值作函数参数

void swap(int a, int b); //无法实现两数据的交换
void swap(int *p, int *q); //开辟了两个指针空间实现交换

2.引用作函数参数

#include <iostream>
using namespace std;
void swap(int &a, int &b){
	int tmp;
	tmp = a;
	a = b;
	b = tmp;
}
int main(){
	int a = 3,b = 5;
	cout<<"a = "<<a<<"b = "<<b<<endl;
	swap(a,b);
	cout<<"a = "<<a<<"b = "<<b<<endl;
	return 0;
}

c++中引入引用后,可以用引用解决的问题。避免用指针来解决。

3.引用提高

引用的本质是指针,C++对裸露的内存地址(指针)作了一次包装。又取得指针的优良特性。所以再对引用取地址,建立引用的指针没有意义

1.可以定义指针的引用,但不能定义引用的引用。

int a;
int* p = &a;
int*& rp = p; // ok
int& r = a;
int&& rr = r;//error

例子:

#include <iostream>
using namespace std;
void swap(char *pa,char *pb)
{
	char *t;
	t=pa;
	pa=pb;
	pb=t;
}
void swap2(char **pa,char **pb)
{
	char *t;
	t=*pa;
	*pa=*pb;
	*pb=t;
}
void swap3(char *&pa,char *&pb)//指针的引用
{
	char *t;
	t=pa;
	pa=pb;
	pb=t;
}
int main()
{
	char *pa="china";
	char *pb="america";
	cout<<"pa"<<pa<<endl;
	cout<<"pb"<<pb<<endl;
	//swap(pa,pb);
	//swap2(&pa,&pb);
	swap3(pa,pb);
	cout<<"pa"<<pa<<endl;
	cout<<"pb"<<pb<<endl;
	return 0;
}

2.可以定义指针的指针,不能定义引用的指针。

int a;
int* p = &a;
int** pp = &p; // ok
int& r = a;
int&* pr = &r; // error

3.可以定义指针数组,但不能定义引用数组,可以定义数组引用。

int a, b, c;
int* parr[] = {&a, &b, &c}; // ok
int& rarr[] = {a, b, c}; // error
int arr[] = {1, 2, 3};
int (&rarr)[3] = arr; // ok

4.常引用

const 引用有较多使用。它可以防止对象的值被随意修改。因而具有一些特性。

(1)const 对象的引用必须是 const 的,将普通引用绑定到 const 对象是不合法的。

这个原因比较简单。既然对象是 const 的,表示不能被修改,引用当然也不能修改,必须使用 const 引用。实际上,const int a=1; int &b=a;这种写法是不合法的,编译不过。

(2)const 引用可使用相关类型的对象(常量,非同类型的变量或表达式)初始化。

这个是const 引用与普通引用最大的区别。const int &a=2;是合法的。double x=3.14; const int&b=x;也是合法的。

4.常引用原理

const 引用的目的是,禁止通过修改引用值来改变被引用的对象。const 引用的初始化特性较为微妙,可通过如下代码说明

double val = 3.14;
const int &ref = val; // int const & int & const ??
double & ref2 = val;
cout<<ref<<" "<<ref2<<endl;
val = 4.14;
cout<<ref<<" "<<ref2<<endl;

上述输出结果为 3 3.14 和 3 4.14。因为 ref 是 const 的,在初始化的过程中已经给定值,不允许修改。而被引用的对象是 val,是非 const 的,所以 val 的修改并未影响 ref 的值,而 ref2 的值发生了相应的改变。

那么,为什么非 const 的引用不能使用相关类型初始化呢?实际上,const 引用使用相关类型对象初始化时发生了如下过程:

int temp = val;
const int &ref = temp;

如果 ref 不是 const 的,那么改变 ref 值,修改的是 temp,而不是 val。期望对 ref 的赋值会修改 val 的程序员会发现 val 实际并未修改。

int i=5;
const int & ref = i+5;
//此时产生了与表达式等值的无名的临时变量,
//此时的引用是对无名的临时变量的引用。故不能更改。
cout<<ref<<endl;

5.const的好处

1,使用 const 可以避免无意修改数据的编程错误。

2,使用 const 可以处理 const 和非 const 实参。否则将只能接受非 const 数据。

3,使用 const 引用,可使函数能够正确的生成并使用临时变量(如果实参与引用参数不匹配,就会生成临时变量)

6.引用的本质浅析

1.大小与不可再引用

struct TypeP
{
	char *p;
};
struct TypeC
{
	char c;
};
struct TypeR
{
	char& r; //把引用单列出来,不与具体的对象发生关系
};
int main()
{
	printf("%d %d %d\n",sizeof(TypeP),sizeof(TypeC),sizeof(TypeR));
	return 0;
}

结论:引用的本质是,是对常指针 type * const p 的再次包装。

1、const int *pi                                   指向常量的指针。
2、int * const pi                                  指针本身是一个常量,称为“指针常量”、“常指针”。
3、const int * const pi                       指向常量的指针常量。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注我们的更多内容!

(0)

相关推荐

  • C++指针与引用的区别案例详解

    C++中指针和引用的区别 从概念上讲.指针从本质上讲就是存放变量地址的一个变量,在逻辑上是独立的,它可以被改变,包括其所指向的地址的改变和其指向的地址中所存放的数据的改变. 而引用是一个别名,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化,而且其引用的对象在其整个生命周期中是不能被改变的(自始至终只能依附于同一个变量). 在C++中,指针和引用经常用于函数的参数传递,然而,指针传递参数和引用传递参数是有本质上的不同的: 指针传递参数本质上是值传递的方式,它所传递的是一个

  • 详解C++数组和数组名问题(指针、解引用)

    目录 一.指针 1.1 指针变量和普通变量的区别 1.2 为什么需要指针 1.3 指针使用三部曲 二.整形.浮点型数组 2.1 数组名其实是特殊的指针 2.2 理解复杂的数组的声明 2.3 数组名a.数组名取地址&a.数组首元素地址&a[0].指向数组首元素的指针*p 2.4 对数组名以及取值符&的理解 三.字符数组数组名 一.指针 1.1 指针变量和普通变量的区别 指针:指针的实质就是个变量,它跟普通变量没有任何本质区别.指针完整的应该叫指针变量,简称为指针. 是指向的意思.指针

  • 详解C++ 引用

    引用变量是一个别名,也就是说,它是某个已存在变量的另一个名字.一旦把引用初始化为某个变量,就可以使用该引用名称或变量名称来指向变量. C++ 引用 vs 指针 引用很容易与指针混淆,它们之间有三个主要的不同: 不存在空引用.引用必须连接到一块合法的内存. 一旦引用被初始化为一个对象,就不能被指向到另一个对象.指针可以在任何时候指向到另一个对象. 引用必须在创建时被初始化.指针可以在任何时间被初始化. C++ 中创建引用 试想变量名称是变量附属在内存位置中的标签,您可以把引用当成是变量附属在内存位

  • C++中指针和引用的区别详解

    C++中指针和引用的区别 指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法. 1.指针和引用的定义和性质区别: (1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已.如: int a=1;int *p=&a; int a=1;int &b=a; 上面定义了一个整形变量和一个指针变量p,该指针变量指向a的存储单元,即p的值是a存储单元的

  • 实例详解C++中指针与引用的区别

    目录 前言 1.指针的声明 2.使用new来分配内存 3.malloc 与 new 的区别 4.引用的声明与本质 总结 前言 在计算机存储数据时必须要知道三个基本要素:信息存储在何处?存储的值为多少?存储的值是什么类型?因此指针是表示信息在内存中存储地址的一类特殊变量,指针和其所指向的变量就像是一个硬币的两面.指针一直都是学习C语言的难点,在C++中又多了一个引用的概念.初学时很容易把这两个概念弄混,下面就来通过一些例子来说明二者之间的差别. 1.指针的声明 上文中提到,指针和其所指向的变量就像

  • C++引用的详细解释

    目录 一.C++ 引用 1.规则 2.应用 3.引用提高 1.可以定义指针的引用,但不能定义引用的引用. 2.可以定义指针的指针,不能定义引用的指针. 3.可以定义指针数组,但不能定义引用数组,可以定义数组引用. 4.常引用 4.常引用原理 5.const的好处 6.引用的本质浅析 总结 一.C++ 引用 变量名,本身是一段内存的引用,即别名(alias).此处引入的引用,是为己有变量起一个别名. 声明如下 int main() { int a; int &b = a; } 1.规则 1.引用没

  • Linux内核宏Container_Of的详细解释

    目录 1. 结构体在内存中是如何存储的 2. container_of宏 3. typeof 4. (((type *)0)->member) 5. const typeof(((type * )0) ->member)*__mptr = (ptr); 6. offsetof(type, member)) 7. (type * )((char * )__mptr - offsetof(type, member)) 8. 举例 1. 结构体在内存中是如何存储的 int main() { Stud

  • linux下的tar命令详细解释

    tar命令 [root@Linux ~]# tar [-cxtzjvfpPN] 文件与目录 .... 参数: -c :建立一个压缩文件的参数指令(create 的意思): -x :解开一个压缩文件的参数指令! -t :查看 tarfile 里面的文件! 特别注意,在参数的下达中, c/x/t 仅能存在一个!不可同时存在! 因为不可能同时压缩与解压缩. -z :是否同时具有 gzip 的属性?亦即是否需要用 gzip 压缩? -j :是否同时具有 bzip2 的属性?亦即是否需要用 bzip2 压

  • cmd 环境变量设置方法详细解释

    cmd设置环境变量可以方便我们bat脚本的运行,但是要注意的是变量只在当前的cmd窗口有作用(局部生效),如果想要设置持久的环境变量需要我们通过两种手段进行设置:一种是直接修改注册表,另一种是通过我的电脑-〉属性-〉高级,来设置系统的环境变量. 1.查看当前所有可用的环境变量:输入 set 即可查看. 2.查看某个环境变量:输入 "set 变量名"即可,比如想查看temp变量的值,即输入 set temp 当然也可以使用echo %temp% 3.修改环境变量 :输入 "se

  • 易语言运算命令的详细解释

    本篇内容针对易语言运算命令的位取反.位于.位或.位异或做了详细解释 易语言3.5版提供了4个位运算命令. 1.位取反 位取反命令将指定数值转换为二进制后,对每一比特位的值取反,即0变为1,1变为0,然后转换成十进制数,返回值是转换后的十进制数. "位取反"命令的命令格式是: 〈整数型〉 位取反 (欲取反的数值) 参数"欲取反的数值"的类型为"整数型". 2.位与 位与命令将所给的数值全部转换为二进制,对所有二进制数值的共同比特位进行"与

  • Python实现随机游走的详细解释

    1.单一的500步随机游走的例子,从0开始,步长为1和-1,且以相等的概率出现. 注:需要python的内置函数random,不需安装,直接导入即可 import random -*- coding: utf-8 -*- import matplotlib.pyplot as plt import random position=0#设置初始位置 walk=[]#保存位置 steps=500#设置步数为500步 for i in range(steps): step=1 if random.ra

  • package.json与package-lock.json的区别及详细解释

    目录 package.json package-lock.json 两者区别: package-lock.json的作用 补充:关于package-lock.json的详细解释 总结 package.json 记录当前项目所依赖模块的版本信息,更新模块时锁定模块的大版本号(版本号的第一位),不能锁定后面的小版本, package-lock.json package-lock.json 是在 `npm install`时候生成一份文件.记录了node_modules目录下所有模块(包)的名称.版本

  • 正则表达式预查的详细解释与应用实例

    目录 解释 应用 难点-为什么.?[^#/n]?.*?不行 总结 解释 预查又称环视(Lookaround).属于零宽断言(Zero-Length Assertions)的一种,有 4 个语法: 语法 中文名 英文名 (?=regex) 肯定性前瞻 Positive lookahead (?!regex) 否定性前瞻 Negative lookahead (?<=regex) 肯定性后顾 Positive lookbehind (?<!regex) 否定性后顾 Negative lookbeh

  • cmd批处理转义字符%的详细解释

    1.%是个ESCAPE字符,通常将之译为转义字符,但也有更形象的译名脱逸字符.逃逸字符等.也就是说%不仅仅将与其相关的特定字符串转义并替换为特定字符串,而且自身也会被"脱逸".而且类似于C语言中的转义字符"\",双%会转义并脱逸为单%,四%则脱为双%. 2.for本身是一个特殊的命令,类似于一个特化的命令解释器,因为它的功能实现需要执行多条语句,因此它必须也具有对命令行(特指do后的命令行)分析处理的功能.而command/cmd实现for时自然会借用自身原有的命令

  • 弹出消息的bat代码(msg命令详细解释)

    复制代码 代码如下: msg * "ok" msg.exe命令是将消息发送给用户. MSG {username | sessionname | sessionid | @filename | *} [/SERVER:servername] [/TIME:seconds] [/V] [/W] [message] username 标识指定的用户名. sessionname 会话名称. sessionid 会话 ID. @filename 识别这样一个文件,该文件含有将所发消息 发送到的用

随机推荐