【C++】C++自学旅程(5):指针和引用

  学C语言的时候,指针一直是一个让人头大的东西,懂,但是不会用,还好现在慢慢会了,还好C++的指针还是跟C基本相同,还好如此我就只用记一些不同的东西了:)

  一、无名变量(动态变量)

  可以用new来创建一个无名变量,这种变量没有标识符,如:

int *p = new int;

  可以在动态创建的同时指定初始化列表,如:

double *pdouble;
pdouble = new double(26.7);

  之后这个变量就通过指针来间接访问,如:

cin>>*p;
cout<<*p;
int c = *p+13;
......

  一般情况下,称使用new运算符创建的变量为动态变量,因为这些变量要在程序运行期间动态创建和销毁。

  动态创建的变量要动态销毁,用delete关键字,如:

delete p;

  酱紫就删除了指针p指向的无名空间。

  接下来,谁来告诉我这玩意有什么用?

 

  二、const修饰指针

  由前面的学习可以知道,const关键字可定义常量,如

const int a=10;

是不能改变的。当const修饰指针,也是不能改的意思,不过他俩结合会有新的火花:

  ①指向常量的指针

  若把const放在声明变量的最左边,如:

1 int i=0;
2 int j;
3 const int *p = &i;
4 *p = 3; //错误!不能通过p修改所指内容
5 i=2; //可以
6 p=&j;

  可以发现,酱,不能再通过p修改所指内容,仅此而已,p所指的东西可以通过别的途径更改,p的指向也可以改。

  ②指针常量

1 int * const p = &i;
2 p=&j; //错误,指针不能修改指向
3 *p=2; //可以

  如果要指针指向固定,且不能通过该指针修改所指值,则这样:

const int * const p = &i;

 

  三、引用

  引用就是给一个变量取个别名,如: 

int a;
int &b = a;

  相当于a有了另一个名字b,只是另一个名字,系统并没有分配另外一个空间给b。用引用可以减少空间消耗。

  需要注意的有:引用声明时必须指定对哪个变量引用,即必须初始化别名不能再被引用不能建立数组的引用,因为数组是元素的集合。

  下面用大篇幅来说说引用的应用:

  ①引用作为函数参数

  函数参数传递有三种方式:值传递、地址传递和引用传递。下面来看一个例子程序,来看看引用传递怎么用:

 1 //引用作为函数参数的引用传递方式
 2 #include<iostream>
 3 using namespace std;
 4 void fun1(int);
 5 void fun2(int&);
 6 
 7 int main()
 8 {
 9     int a=2;
10     cout<<"实参a的地址是:"<<&a<<endl;
11 
12     fun1(a);
13     cout<<"主调函数中a="<<a<<endl;
14 
15     fun2(a);
16     cout<<"主调函数中a="<<a<<endl;
17 
18     return 0;
19 }
20 
21 void fun1(int x)
22 {
23     cout<<"值传递中,形参x的地址是:"<<&x<<endl;
24     x=10;
25     cout<<"在fun1函数内部x="<<x<<endl;
26 }
27 
28 void fun2(int& x)
29 {
30     cout<<"引用传递中,形参x的地址是:"<<&x<<endl;
31     x=10;
32     cout<<"在fun2函数内部x="<<x<<endl;
33 }

  运行结果如下:

实参a的地址是:0x68feec
值传递中,形参x的地址是:0x68fe90
在fun1函数内部x=10
主调函数中a=2
引用传递中,形参x的地址是:0x68feec
在fun2函数内部x=10
主调函数中a=10

  可以发现,fun1没有用引用传递,fun1中定义的局部变量x的地址与实参不同,改变形参的值当然也无法对实参a起到作用。而在fun2中,x并不是新定义的局部变量,而是对实参a的引用,所以fun2中的x就是a,地址也相同,那么对引用量x进行变化,实参当然受影响。

  总结一下引用传递的优点或者特点:

    • 引用传递和指针传递效果一样,被调函数中对引用的操作,实际上就是对实参的操作。
    • 使用引用传递,并没有产生实参的副本,而是直接对实参操作,比较节省内容,因此在数据量大时,用引用比一般传递参数的效率和所占空间都好。
    • 引用传递较指针来说,优点同样有节省空间,因为指针仍然需要为形参开辟空间,且引用传递在使用起来比指针方便(不用经常使用*或&符号)。

  ②常引用

  如:

const int &b=a;

  这样就不能通过引用对值进行变更了,更加安全咯~据说能使用const的情况下尽量使用const,虽然我现在还不能完全理解这样做的苦衷。

  ③引用作为返回值

  要用引用作为返回值类型时,函数得这么定义,如:

int &fun(形参列表)

  相信用起来没有什么问题吧!~

  但是要注意的是:不能返回局部变量的引用,因为局部变量被灭的,引用就会“无所指”,程序会进入位置状态;);也不能引用new定义的动态变量;可以返回类成员的引用,但最好用const。

  之后再继续学吧,好晕啊@~@!

 

  四、动态数组

  原来之前学的动态变量 new/delete 语句是用在这里啊!申请动态数组如下:

数据类型 * p = new 数据类型[n];
//其中n可以为变量

  相当于p指的是这个空间的收地址,跟数组一样咯,但是可以自由控制n的大小了。用完后删除:

delete []p;

  特别注意删除语句的形式:[]p!要加方括号在指针前面。

  温馨提示:使用了new,指针p就不要更改了,免得出现错误。

  学到这个,突然回忆起了在C语言的malloc/free函数,C++也是有这个函数的。所以new/delete和malloc/free有什么不同呢?好奇搜索了一下,原来这是百度的一个笔试题。。。

百度笔试题:malloc/free与new/delete的区别》by CSDN hackbuteer1

  真是深刻感受到知识都来源于生活,小东西也要注意,说不定哪天就派上了大用场。。。不过,不同点第一条(操作对象不同)现在还看不懂。

 

  五、其他指针复习

  ①函数指针

  指向函数的指针。形如:

int (*p)(int,int,int);
p=max;

  这样,p就指向max了。圆括号不能少!

  ②指向指针的指针

  指的对象还是指针。

int *p=&x;
int **p=&p;

  ③指针数组

  数组元素为指针类型的数据。

int *p[5];

  P.S.   int *p[5] 和 int (*p)[5] 辨析

  前者,p优先与[]结合,所以p是一个指针,指向一个有五个数据的数组。

  后者是指针数组,数组元素为指针。

 

  数组中举结了@~@

 

posted @ 2016-02-02 10:35  HappyCtest  阅读(363)  评论(0编辑  收藏  举报