c++学习(2.3)引用

复合类型是指基于其他类型定义的类型。 c++语言有几种复合类型, 这里将介绍其中的两种:引用和指针。

引用

·

·

·

·

基础引用

在c++11版本中引入了“右值引用”, 关于这个我们在这里先不讲解。 这种引用主要作用于内置类型。 严格的来说, 我们使用术语“引用”的时候, 默认的就是左值引用。

引用就像是为对象起了另外一个名字, 引用类型引用另外一种类型。 我们通过将声明写成&d的形式来定义引用, 其中d是声明的变量名:

    int ival = 1024;      //定义一个int类型变量
    int &refVal = ival;   // int类型refVal变量是对ival的一个引用
    int &refVal2;         //错误! 引用在定义的时候必须被初始化。

·

·

引用 == 别名

一般在初始化变量的时候, 初始值会被拷贝到新建的对象之中。 然而定义引用的时候, 程序吧引用和它的初始值绑定在一起, 而不是将初始值拷贝给引用。 一旦初始化完成, 引用将和他的初始值对象一直绑定在一起。 因为无法令引用重新绑定另外一个对象, 因此引用必须初始化。

定义了一个引用之后, 对其(这里指引用)所有的操作都是在与之绑定的对象上进行的。

    int ival = 1024;           //定义一个int类型变量
    int &refVal = ival;        // int类型refVal变量是对ival的一个引用
    refVal = 2;                //等价于ival = 2, 把2赋值给了引用绑定的对象;
    int ii = refVal;            //与ii = ival的调用效果一样

为引用赋值, 实际上是八值赋给了与引用绑定的对象, 获取引用的字, 实际上是获取与引用绑定的对象的值。 同理, 以引用作为初始值, 实际上是与引用绑定的对象作为初始值。

    int ival = 1024;          //定义一个int类型变量
    int &refVal = ival;       // int类型refVal变量是对ival的一个引用
    int &refVal3 = refVal;    // 正确! 这里rafVal3是inval的引用!!
    int i = refVal;           // 正确i被初始化为ival的值;

在这里我们要注意, 引用本身不是一个对象, 所以我们不能定义引用的引用。

上个代码中int &refVal3 = refVal;实际上是在定义int &fefVal = ival

·

·

引用的定义

允许值啊一条语句之中定义多个引用, 其中每个引用都必须以符号&开头;

    int i = 1024, i2 = 2048;    //这里定义两个int类型的变量i、i2
    int &r = i, r2 = i2;        //这里r是一个引用, 与i绑定在一起, r2是int类型
    int i3 = 1024, &r1 = i3;    // i3是int类型, ri是一个引用, 与i3绑定在一起。
    int &r3 = i3, &r4 = i2;     //r3 和r4 都是引用

除了我们接下来将要介绍的两种情况之外, 其他所有的有引用的类型都要和与之绑定的对象严格匹配。并且引用只能绑定在对象上, 而不能与字面值或者某个表达式计算结果绑定在一起!!

int &refVal4 = 1024     //错误!只能绑定在对象上
double dval = 3.14;
int &refVal5 = dval     //错误!此处引用的类型和初始值的类型必须相同

·

·

·

·

const的引用

我们可以把引用绑定到const上, 就像绑定到其他对象上, 我们称之为对常量的绑定。 与普通引用不同的是, 对常量的引用不能被用作修改它所绑定的对象。

    const int a = 1024;   //定义一个int 类型的常量 a
    const int &b = a;     //定义一个常量引用b 与a绑定
    a = 42;               // 错误!!!! a是常量不能改变他的值
    int &d = a;           // 错误 常量只能被常量引用所引用

因为a是常量, 我们不允许直接去为a赋值, 当然也就不能通过引用去改变a的值。 因此, 对d的初始化是错误的。 假设该初始化合法, 则可以通过const来改变他所引用的对象的值, 这显然是不合法的。

这里多说两句

const int &b = a; 中的const属于底层const 也就是对b的限定: 通过b修改值是不合法的

这里我们用指针来举例:

int a;

int const *b = a 这里指b的指向不会发生改变, 只能指向a

const int *c = a 这里指不能通过c去修改a的值

·

·

初始化和对const的引用

在上文中我们提到, 引用的类型必须与其引用对象的类型一致, 但是有两个例外。 第一种意外情况就是在初始化常量引用的时候允许任意表达式作为初始值, 只要该表达式可以转换为引用的类型即可(也就是在引用的时候发生了强制类型转换); 另一种情况是, 常量引用绑定一个非常量的对象、字面值甚至是一个表达式。注意这两种特殊情况都是常量引用下的特殊, 也就是在基础引用的情况下是不存在特殊情况的

偷个懒直接上图:

想要理解这种例外的真正原因, 最简单的方法是弄清楚一个常量引用是如何被绑定到另外一个类型上的。

·

·

此次, ri引用了一个int类型的数。 对ri的操作应该是整数运算, 但那时dval却是一个双精度浮点数而非整数。因此为了确保让ri绑定一个整数, 编译器把上述代码转变成了下文的形式:

在这种情况下, ri绑定了一个临时量的对象, 所谓临时量的对象就是编译器需要一个空间来暂存表达式的求值的结果所临时创建的一个未命名的对象。 临时变量对象通常被简称为临时量。

接下来探讨ri不是常量时, 如果执行了类似于上面初始化的过程将带来什么。

如果ri不是常量, 如果执行了类似上面的操作, 就允许对ri赋值, 这样就会改变ri所引用的对象的值。 注意, 此时绑定的对象是一个临时变量而不是dval。 程序既让想让ri引用dval, 就肯定想通过ri改变dval的值, 否则ri的存在将无意义, 如此看来既然大家基本不会想把引用绑定到临时变量上, c++也就将这种行为归为非法。

·

·

对const的引用可以引用一个并非const的变量

必须认识到, 常量引用仅仅对引用课参与的操作进行了限定, 对于引用的对象本身是不是一个常量为未出限定。 因为对象也可以是一个非常量, 所以允许通过其他途径改变他的值;

r2非常量绑定整数i是合法行为。 然而, 不允许通过r2修改i的值。 尽管如此, 我们依然可以通过其他途径来修改i的值。 既可以直接给i赋值, 也可以通过像人一样绑定到i的其他引用来修改值。

c++中引用的实现本质是地址的传递

时间: 2024-11-14 07:49:52

c++学习(2.3)引用的相关文章

学习ASP 文件引用常识

ASP 文件引用 Previous Page Next Page #include 命令用于在多重页面上创建需重复使用的函数.页眉. 页脚或者其他元素等. #include 命令 通过使用 #include 命令,我们可以在服务器执行 ASP 文件之前,把另一个ASP文件插入 这个文件中.#include 命令用于在多重页面上创建需重复使用的函数.页眉.页脚或者其 他元素等. 如何使用 #include 命令 这里有一个名为 "mypage.asp" 的文件: <html>

swift 学习之自动引用计数

swift 学习之自动引用计数 学习和研究的主要是"实例对象和实例对象直接的相会强引用所产生的内从泄漏"和"使用闭包产生的强引用造成的内存泄漏" 注意:只有以引用类型存储或者传递的才会存在自动引用计数,比如类,闭包,而枚举.结构体等这都是值存储,值传递不存在引用计数问题(其实也就是Object-c中我们熟悉的ARC,和他的原理是一样的) 实例对象和实例对象之间的相互引用造成的内存泄漏 1>产生原因 两个类中都有对方类的实例变量作为自己的属性,举个例子:创建一个

PHP的学习--图解PHP引用

在一篇文章中看到关于PHP引用的图解,对于加深对PHP引用的理解很有帮助,在这里备份一下. 如果你对PHP的引用一点也不了解,可以先看我之前的博客:PHP的学习--PHP的引用

C++学习笔记之 引用

先声明一下,这里的内容大多是<C++编程思想>中的内容,我最近在学习C++,觉得里面的很多话不错,另外例子也都自己实验了一番,有些现象很有趣,希望与大家分享. ?引用(reference)(&)就像能自动地被编译器间接引用的常量型指针. #include <iostream> using namespace std; int y; int& r = y;//当一个引用被创建的时候,它必须被初始化为一个对象. //你也可以这样写: const int& q =

Java学习之一(引用相关)

1.Java概述 首先,Java是一门面向对象的编程语言.相对于C/C++等语言,Java中没有指针,但是这不代表指针等知识不重要:Java中不存在多继承但是存在多接口.在我自己的学习过程之中,我偏向于实现接口的方式进行编程,因为Java不支持多继承,而支持多接口. Java具有跨平台开发的特点.Java可以编写桌面应用.Web应用程序.分布式系统和嵌入式系统等应用程序等.我主要是往Web应用程序学习. 2.Java命名习惯 包名:统一小写 例如:org.study.pojo(三个文件夹) 常量

PHP的学习--PHP的引用

引用是什么 在 PHP 中引用意味着用不同的名字访问同一个变量内容.这并不像 C 的指针,替代的是,引用是符号表别名.注意在 PHP 中,变量名和变量内容是不一样的,因此同样的内容可以有不同的名字.最接近的比喻是 Unix 的文件名和文件本身——变量名是目录条目,而变量内容则是文件本身.引用可以被看作是 Unix 文件系统中的 hardlink. 引用做什么 PHP 的引用允许用两个变量来指向同一个内容.意思是,当这样做时: <?php $a =& $b; ?> 这意味着 $a 和 $

C语言学习笔记(2):引用头文件所使用的符号区别

C语言引用头文件使用的符号有两种,以头文件stdio.h为例: (1)#include <stdio.h> (2)#include “stdio.h” 这两种引用方式是存在不同的. 第一种引用方式,编译器仅在标准库头文件中进行匹配: 第二种引用方式,编译器先在工程目录下进行匹配,如果没有,再到标准库头文件中查找. 这里进行了测试,应用VC++6.0,新建文件,首先是主文件Test.c: #include <child.h> void main() { Test(); } 然后,为了

C++学习记录(1)——引用

#include <iostream> #include <stdlib.h> using namespace std; /*通过此程序可以发现引用的引用变了,原来的值还是会变, *所以定义函数的时候,如果想让实际变量发生变化,形式 *参数可以定义成引用的形式.另外要注意的是,这里的&不 *是C中的取地址符号,而是引用的意思. */ int main(int argc, char** argv) { //定义两个变量 int x = 100; int y = 200; //

C++学习基础篇 —— 引用(&amp;)的用法和应用

一.引用简介 引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样. 引用的声明方法:类型标识符&引用名=目标变量名: [例1]: int a; int &ra=a; //定义引用ra,它是变量a的引用,即别名 说明: (1)&在此不是求地址运算,而是起标识作用. (2)类型标识符是指目标变量的类型. (3)声明引用时,必须同时对其进行初始化. (4)引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名. r

Java学习---- 数组的引用传递

1. public class ArrayRefDemo01{ public static void main(String args[]){ int temp[] = {1,3,5} ; // 利用静态初始化方式定义数组 fun(temp) ; // 传递数组 for(int i=0;i<temp.length;i++){ System.out.print(temp[i] + ".") ; } } public static void fun(int x[]){ // 接收整型