引用概念
引用不是定义一个变量,而是给一个已经定义的变量重新起一个别名
引用的定义格式:
类型&引用变量名=已定义过的变量名。
引用的特点:
1)一个变量可用多个别名;
2)引用必须初始化;
3)引用只能在初始化的时候引用一次,不能改变为再引用其他的变量。
代码:
#include<iostream>
using namespace std;
int main(){
int a = 10;
int b = 11;
int& c = a;
int& d = a;
//int& d;//error,引用必须要初始化
cout << &a << endl;
cout << &b << endl;
return 0;
}
运行结果显示:a与b的地址相同
const引用
int main(){
int a = 4;
int& b = a;
a = 5;//a改变,b也会改变
b = 6;//b改变,a也会改变
int a1 = 40;
const int& a2 = a1;
a1 = 50;//a1改变,a2也会改变
//a2 = 60;//error,不能给常量赋值
const int& a3 = 5;//常量具有常性,只有常引用可以引用常量
//a4是double类型,a5是int类型,a4赋值给a5时要生成一个临时变量,也就是说d10引用的是这个带有常性的临时变量,所以不能赋值。
double a4 = 1.1;
//int& a5 = a4;//error
const int& a6 = a4;
return 0;
}
函数参数的三种传递方式
1.值传递:如果形参为非引用的传值方式,则生成局部临时变量接收实参的值。
(由于函数体内的参数是外部变量的一份拷贝,改变参数的值不会外部变量)
2.引用传递:如果形参为引用类型,则形参是实参的别名。
(由于函数体内的参数是外部变量的引用,函数体内参数和外部变量是同一个数)
3、指针传递:由于函数体内的参数是指向外部变量的指针,改变该指针指向的内存单元的内容将导致外部变量的值改变(
返回函数值
1、传值作函数返回值&传引用作函数返回值
代码:
int& Func1(int x, int y)//传引用作函数返回值
{
int ret = 0;
ret = x + y;
return ret;
}
int add2(int x, int y)//传值作函数返回值
{
int ret = 0;
ret = x + y;
return ret;
}
1)不要返回一个临时变量的引用。
2)如果返回对象出了当前函数的作用函数域依旧存在,则最好使用引用返回,因为这样更高效。
指针和引用的对比
1、引用在创建的同时必须初始化,即引用到一个有效地对象;而指针在定义的时候不必初始化,可以在定义后面的任何地方重新赋值。
2.不存在空引用,但是有空指针。有多级指针,但是没有多级引用
【例】const int& rlin = 0;
(理解)其语义并非是把引用初始化为NULL,而是创建一个临时的int对象并用0来初始化它,然后在用它来初始化引用rlin,该临时对象将一直保留到rlin销毁的时候才会销毁。因此,不要用字面常量初始化引用
3、引用一旦初始化指向一个对象,它就不能被改变为对另一个对象的引用(即“从一而终”),但是可以被赋值,给引用赋值并不是改变它和原始对象的绑定关系;而指针可以改变为指向另一个对象。
4、引用的创建和销毁并不会调用类的拷贝构造函数和析构函数。
5、在语言层面,引用的用法和对象一样,在二进制层面,引用一般都是通过指针来实现的,只不过编译器帮助我们完成转换。
6、在sizeof中含义不同,引用结果为引用类型的大小,但是指针始终是地址空间所占字节的大小(在32位平台中占4个字节)。