C++的常量、指针、引用

一、C语言的常量是可以通过地址进行修改的;而C++的常量是不可修改的,且在定义的时候必须初始化!

  可引用常量的地址,但只是临时地址:

  const int a = 10 ;

  int *b = (int*)&a ; //开辟临时地址给a,实际并不能访问a的地址,它在符号表中,不可修改

  宏是在预编译阶段(预处理)处理的,而常量是在编译阶段处理的。而且宏没有作用域的说法,从它定义的位置开始到代码结束都可以使用该宏常量。

  

  const修饰的指针,通常如下三种:

  

  

  常量指针(有点难):

  int const a = 10,int * const p = NULL,都在常量区符号表中?

  数组int array[10],10个int数据在栈中,而array常量指针在常量区符号表中,不可修改,但内容是可以修改的。

  引用int &r = a,r是常指针在常量区,指向a变量,r不可改变,而使用时就是*r,就取的是a的值了。

  

二、C++中引用相当于给变量取别名,且定义引用变量时必须初始化:

  int a = 10;

  int *p = &a; //此处&表示取a地址赋给指针p

  int &re = a; //此处&表示引用类型的变量,re就是a的别名,可以对re赋值达到修改a的目的

  int &re2 = re; //可以对引用再次引用,其实re2本质也是a别名

三、通过指针和引用两种方式改变变量的值(如下图)

  有变量a,如果函数的参数为指针int *p,那么传参时应该传的是地址&a;

  如果函数的参数为引用int &r,那么传参时应该直接传a;

  为什么把函数参数类型改为int b,就是实现不了对a的值的修改呢?因为此时传进去的a为形参,作用域只在函数内部,与实际a的地址并不一样,所以不能实现对a值的修改。

  

四、指针、引用作为函数参数

  如果需要传进的参数是一个结构体之类的变量,数据会很多,此时直接传参会存在值拷贝的动作,如果使用指针或引用就可以避免,如下图:

  用指针时,取结构体属性(成员)使用'->'符号;

  用引用时,取结构体属性(成员)使用'.'符号。

  

五、引用的本质

  注:在研究引用时,可按如下理解,但是编程时只需要把引用当做变量的别名即可!

  常量要初始化,引用也要初始化,从这个角度可推测引用可能是一个常量,也就是说是常指针,有引用int &a,其本质形式为int *const a;

  常指针int *const a,即可以通过*a = 10的方式赋值,但指针的指向不能修改,必须指向某一固定地址。

  在引用作为函数参数时,如int &a,直接传参数a,实际编译器隐藏了取地址操作给引用int &a = &a,‘&’被隐藏;

  函数内部对一个引用操作赋值的时候,编译器隐藏了‘*’操作,实际a = 200,即为*a = 200。

六、引用作为函数的返回值

  直接上个C++代码的例子吧:

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<iostream>
 3 #include<stdlib.h>
 4 
 5 using namespace std;
 6 /*
 7 malloc的全称是memory allocation,中文叫动态内存分配,用于申请一块连续的指定大小的内存块区域
 8 以void*类型返回分配的内存区域地址,当无法知道内存具体位置的时候,想要绑定真正的内存空间,就需要用到动态的分配内存。
 9 void* 类型表示未确定类型的指针。C,C++规定,void* 类型可以通过类型转换强制转换为任何其它类型的指针。
10 */
11 
12 char * getmem(int num) {
13     char *p = NULL;
14     p = (char*)malloc(num);//malloc()函数,动态分配内存
15     return p;//返回地址
16 }
17 
18 //两个指针的目的是把一个指针传出来
19 int getmem2(char **pp, int num) {
20     char *p = NULL;
21     p = (char*)malloc(num);
22     *pp = p;//指向指针的指针,二级指针
23     return 0;
24 }
25 
26 int getA1() {
27     int a = 10;
28     return a;
29 }
30 
31 int getA2(int *a) {
32     return 0;
33 }
34 
35 //引用作为返回值时,不要返回局部变量的引用
36 int& getA3() {
37     int a = 10;
38     return a;//隐式操作int &temp = a; temp 为a的别名
39 }
40 
41 int & getA4() {
42     static int a = 10;//静态变量,全局领域开辟的空间,只有程序结束才会释放
43     return a;
44 }
45 
46 int main(void) {
47     int a = 0;
48     char *pp = NULL;
49 
50     a = getA1();//此时是一个值拷贝过程
51     pp = getmem(10);//也是值拷贝,拷贝的是地址
52     cout << "-----------------" << endl;
53     int main_a = 0;
54 
55     main_a = getA3();//main_a = temp//数值拷贝
56     cout << "main_a=" << main_a << endl;
57     cout << "-----------------" << endl;
58 #if 0
59     int &main_a_re = getA3();//再次对temp去别名,本质上还是局部变量a的别名
60     cout << "main_a_re=" << main_a_re << endl;//第一次调用还未压栈
61     cout << "main_a_re=" << main_a_re << endl;//再调用时main_a_re,因为a是局部变量,压栈后内存被释放,这个别名就出现异常
62 #endif
63     int &main_a_re = getA4();
64     cout << "main_a_re=" << main_a_re << endl;
65     cout << "main_a_re=" << main_a_re << endl;
66     //引用作为函数返回值的话,函数可以当左值
67     getA4() = 1000;
68 
69     system("pause");
70     return 0;
71 }

七、指针引用

  

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<iostream>
 3 #include<stdlib.h>
 4 
 5 using namespace std;
 6 struct teacher {
 7     int id;
 8     char name[64];
 9 };
10 
11 //二级指针**tpp这种形式就是最外层指针的内容是一个指针
12 int get_mem(struct teacher** tpp) {
13     struct teacher *tp = NULL;
14     tp = (struct teacher*)malloc(sizeof(struct teacher));
15     if (tp == NULL) {
16         return -1;
17     }
18     tp->id = 100;
19     strcpy(tp->name, "li4");
20     *tpp = tp;//指针指向指针,就是新的指针tpp是用来保存第一层指针tp的
21     return 0;
22 }
23 
24 void free_mem(struct teacher **tpp) {
25     if (tpp == NULL) {
26         return;
27     }
28 
29     struct teacher *tp = *tpp;//一级指针*tpp赋给临时变量tp
30     if (tp != NULL) {
31         free(tp);//释放最里层的一级指针,内容为结构体
32         *tpp = NULL;
33     }
34 }
35 
36 int get_mem2(struct teacher *&re) {
37     re = (struct teacher*)malloc(sizeof(struct teacher));
38     if (re == NULL) {
39         return -1;
40     }
41     re->id = 200;
42     strcpy(re->name, "wang5");
43     return 0;
44 }
45 
46 void free_mem2(struct teacher *&re) {
47     if (re != NULL) {
48         free(re);
49         re = NULL;
50     }
51 }
52 
53 int main(void) {
54     struct teacher *tp = NULL;
55 
56     get_mem(&tp);//不论是几级的指针,传进的参数都是地址,所以用&tp
57     cout << "id=" << tp->id << ",name=" << tp->name << endl;
58     free_mem(&tp);//释放最外层的指针
59     cout << "------------------" << endl;
60     get_mem2(tp);//用引用时,tp就是定义中的&tp
61     cout << "id=" << tp->id << ",name=" << tp->name << endl;
62     free_mem2(tp);
63     system("pause");
64     return 0;
65 }

八、const引用

   

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include<iostream>
 3 #include<stdlib.h>
 4 
 5 using namespace std;
 6 
 7 int main(void) {
 8     const int a = 10;//如果对常量进行引用,那么必须是一个const引用
 9     const int &re = a;
10 
11     int b = 20;
12     const int &re2 = b;//相反如果一个普通变量,用一个const引用接收是可以的
13     
14     system("pause");
15     return 0;
16 }

 

posted @ 2018-11-24 12:33  zarjen  阅读(815)  评论(0编辑  收藏  举报