C++学习笔记3
1.3引用
1.3.1
C语言中可以使用指针改变实参的值,在C++中可以使用引用更简洁。另外,参数是值传递,函数域中形参重新分配内存,而把实参的值传递到新分配的内存中,或者实参是一个复杂的对象,需要重新分配内存,使得效率降低。 引用声明如下:类型标识符 &引用名 = 目标变量名; 例如:
float a ;
float &pa = a;.
类型与人的小名,外号例如:鲁迅和周树人是同一人。由于只是一个代号,所以pa本身并没有另辟内存,周树人就是鲁迅,陆逊就是周树人。有个别名并没有创造新的鲁迅。 注意:这里&是引用符号不是地址符号。 引用需要注意以下几点: (1)声明一个引用的时候同时需要初始化,因为它是某一变量的别名。例如:没有鲁迅就没有周树人,在鲁迅这个新名字开始使用时,就意味着时鲁迅等同于周树人了。
int a=1 ,b=2;
int &t=a;
int &t;
(2)当一个引用声明完毕后,相当于目标变量有两个名字引用名和原名字,在执行该函数时不可以其他变量在使用该引用名,鲁迅这个名字正在被周树人用,其他人此时再用会冲突。
int a=1 ,b=2;
int &t=a;
int t = b;
(3)一个引用也可以有引用,相当于一个变量有两个引用,两个新的名字,
int a=1;
int &b=a;
int &c=a;
(4)引用不能为空。
int a =3;
int &b=a;
int &c=NULL;
观察下面的例子:
#include<iostream>
using namespace std;
int main()
{
int x,y=36;
int &refx=x,&refy=y;
refx = 12;
cout<<"x="<<x<<" "<<"refx="<<refx<<endl;
cout<<"y="<<y<<" "<<"refy="<<refy<<endl;
refx = y;
cout<<"x="<<x<<" "<<"refx="<<refx<<endl;
cout<<"&x="<<&x<<" "<<"&refx="<<&refx<<endl;
cout<<"&y="<<&y<<" "<<"&refy="<<&refy<<endl;
return 0 ;
}
运行结果:
x=12 refx=12
y=36 refy=36
x=36 refx=36
&x=0019FF2C &refx=0019FF2C
&y=0019FF28 &refy=0019FF28
Press any key to continue
从上面结果可以看出,y只是赋值给refx,但是并没有改变原来的地址,refx仍然是和x绑定在一起,refx和x同一内存空间。
1.3.2 引用作为函数参数
引用在C++中主要有两个作用作为函数参数,和作为函数返回值。其中主要利用的是作为函数参数,传递数据的功能。 传统C语言中,函数在调用时,参数是通过值来传递的(实参赋值给形参),也就是说函数的参数不具备返回值的能力,是单向传递的,在函数运行时,实参与形参不占据同一个内存单元。 例子:实现两个变量的值互换。
#include<iostream>
using namespace std;
void swap(int a,int b)
{
int temp;
temp =a;
a=b;
b=temp;
}
int main()
{
int n=1,m=2;
cout<<n<<","<<m<<endl;
swap(n,m);
cout<<n<<","<<m<<endl;
return 0;
}
运行结果
1,2
1,2
Press any key to continue
正如上面所述,实参赋值给形参变量,形参在函数运行时交换数值,结束时释放,除去赋值过程其他与实参无关。
#include<iostream>
using namespace std;
void swap(int *a,int *b)
{
int temp;
temp =*a;
*a=*b;
*b=temp;
}
int main()
{
int n=1,m=2;
cout<<n<<","<<m<<endl;
swap(&n,&m);
cout<<n<<","<<m<<endl;
return 0;
}
运行结果:
1,2
2,1
Press any key to continue
如上面程序看到n,m变量的地址传递给了指针变量啊a,b。此时a,n为指向同一内存单元,m,b同理也是,当a,b交换了他们所指向的值意味着n,m交换了值,且函数结束时,只是变量a,b被释放,所以成功交换。这样做需要占用新的内存空间用指针运算符去兜一圈访问。使用引用就可以成功解决麻烦。 通过引用交换两个整数:
#include<iostream>
using namespace std;
void swap(int &a,int &b)
{
int temp;
temp =a;
a=b;
b=temp;
}
int main()
{
int n=1,m=2;
cout<<n<<","<<m<<endl;
swap(n,m);
cout<<n<<","<<m<<endl;
return 0;
}
运行结果:
1,2
2,1
Press any key to continue
相当于int &a=n,&b=m; 此时n,m有了小名,利用别名交换数值,然后释放别名。这样看起来很简洁。 有了对以上引用的熟悉,所以进一步细节的讨论:
- 不能建立void类型的引用,如:
void &a=9; //错误; 因为任何变量都不是void类型的,void的含义是 无类型或者空类型,void只是在语法上相当于类型而已。 - 不能建立数组。如:
char c[6]=“hello”; char&r[6]=c; //错误 企图建立一个6个元素的引用的数组,数组名只代表数组的首地址。 - 可以将变量的引用地址赋值给一个指针,此时指针指向原变量。
int a=3;//变量类型整形 int int &b=a;//变量类型int, 此时&为引用声明 int *p=&b;//地址b被编译器认为是‘int *’ 下面这个是错误的: int &*p=&a; //此时编译器认为int &*为int * * ,在不是指针定义是认为p是int *在加上外面的,所以为int **,这里企图定义指向引用类型的指针变量p(int &) int *&p=&a;//error 编译器认为int *&和int *无法转换,我认为和上面类似错误int * *不能和 int *转化 由于引用不是一种独立的数据类型,因此不能建立指向引用类型的指针变量。 为了便于记忆这些奇怪的符号,左边在定义时英文字母都是新的变量,右边的是以前定义过的。奇怪的符号都是修饰符。 - 建立指针变量的引用
int i =5; // int *p=&i; // int *&pt=p; //个人理解:整个一句话必然说明pt是某一个变量的引用,int * 说明pt是一个指向整形变量的指针变量类型(类型是pt变量的属性,&则是声明我是在引用)由于是指针变量类型所以右边是一个指针变量p,也就是再给p起一个名字但是类型必须得对应上。 - 可以用const限定,不允许改变变量的值。
int i = 5;//定义整形变量i,初值为5 const int &a=i;//声明常引用,不允许改变a的值 a=3;//错误 i=3;//true ,此时输出i和a的值都是3 这个特性经常被用来保护形参不被改变
函数通常只返回一个值,通过引用相当于函数返回指定位置多个值。 例如:编写一个函数实现返回多个值。 方法一利用指针:
#include<iostream>
using namespace std;
void f(int,int*,int*);
int main()
{
int x1,x2,x3;
x1=20;
f(x1,&x2,&x3);
cout<<x1<<" "<<x2<<" "<<x3<<endl;
return 0;
}
void f(int n,int *n1 ,int *n2)
{
*n1 = n+10;
*n2 = n-10;
}
运行结果:
20 30 10
Press any key to continue
方法二利用引用:
#include<iostream>
using namespace std;
void f(int,int&,int&);
int main()
{
int x1,x2,x3;
x1=20;
f(x1,x2,x3);
cout<<x1<<" "<<x2<<" "<<x3<<endl;
return 0;
}
void f(int n,int &n1 ,int &n2)
{
n1 = n+10;
n2 = n-10;
}
运行结果:
20 30 10
Press any key to continue
若以引用作为函数返回值,则函数定义成以下格式: 类型标识符 &函数名(形参列表以及类型说明); {函数主体} 例子:
#include<iostream>
using namespace std;
int f;
int f1(int a);
int &f2(int a);
int main()
{
int n =f1(2);
int m =f2(5);
cout<<n<<" "<<m<<endl;
return 0;
}
int f1(int a)
{
f =3*a;
return f;
}
int &f2(int a)
{
f = 3*a;
return f;
}
运行结果:
6 15
Press any key to continue
f1和f2的不同在于返回值不产生临时变量,不占用系统内存。 f1返回6时通过局部变量传递给n,而f2相当于返回全局变量的引用. 以上有个人理解,有可能存在错误!!!! ┭┮﹏┭┮
|