C++ 引用和指针 Posted on 2019-02-20 | Edited on 2019-03-21 | In C++ | Views: 引用1234567891011121314151617181920// C++ 的标准输入,输出头文件#include<iostream>void main(){ // 变量的内容保存在特定的内存地址中,而变量名则可以认为是该地址名的别名 int a = 10; // 在C++中,我们可以通过引用,为一个变量定义新的别名 int &b = a; // &b表示了让b拷贝a的特性, // 区别于指针,为p赋值a的地址; // 实际引用和指针的效果是类似的! // 指针可以理解为多保存一份变量的地址,变量值是地址,要通过地址取实际的变量值,需要多一步,用*,取地址运算 // 引用可以理解为省略了指针用*取值的步骤,因为引用和原变量名的作用是一致的,就是一个别名,直接通过引用就能 // 拿到实际变量的值(可以认为,引用比指针消耗更少,因为引用不需要再保存一份地址) int *p = &a; cout << b<<endl; system("pause");} 引用传递12345678910111213141516171819202122232425262728293031323334353637383940414243// C++ 的标准输入,输出头文件#include<iostream>void swap_1(int *a, int *b){ int c; c = *a; *a = *b; *b = c;}// 通过引用进行交换// a和b此时不再是进行值传递,而是通过了引用传递// 此时的a和b就是调用处的传进来的参数,而不是新的变量void swap_2(int &a, int &b){ int c; c = a; a = b; b = c;}// 引用的主要作用是作为函数的参数和返回值:// 1,通过引用进行调用,比通过指针调用更加简便,省去了添加*,进行取值// 2,通过引用作为参数传递,可以直接传递原值,在函数中直接操作源参数,减少参数传递过程中产生的副本,提高效率// 3,我们可以直接通过引用操作源变量,而指针必须通过取值(*p)才能间接操作,且从可读性上讲,指针更差;void changeAge(Teacher &t){ t.age = 100;}void main(){ int x = 10, y = 20; cout << "a = " << x << "b = " << y << endl; // 通过指针进行值交换 swap_1(&x, &y); cout << "a1 = " << x << "b1 = " << y << endl; // 通过引用进行值交换 swap_2(x, y); cout << "a2 = " << x << "b2 = " << y << endl; system("pause");} 指针引用123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475void getTeacher(Teacher **p){ // 定义一个指针,并让它指向申请的内存空间的首地址,详单与为其赋值该内存空间地址 Teacher* t = (Teacher*)malloc(sizeof(Teacher)); // p是二级指针,其应该赋值指针变量的地址 //p = &t; // *p表示取值其地址的内容,其原先保存的是指针的地址,取值则表示取值对应地址的指针变量 // t就是一个指针变量,可以直接赋值给*p *p = t; // 一级指针的取值 (*t).age = 20; t->age = 21; // 二级指针的取值:先取到一级指针变量值(*p),即指针保存的变量地址,然后取到一级指针指向的变量,及变量地址指向的变量内容(**p) (*p)->name = "hsh"; (**p).name = "hsh";}// 定义一个指针引用,指针引用可以省略前面的*号void getTeacher(Teacher *&p){ // 引用是指针变量的别名(sizeof引用得出的大小就是对应变量的大小),也可以认为,它就是一个一级指针变量 p = (Teacher*)malloc(sizeof(Teacher)); // 一级指针的赋值操作 p->name = "hsh"; p->age = 20;}// 此处如果传递一个一级指针变量,则无法对指针进行初始化void getTeacher2(Teacher *t){ // 传递一个Teacher变量的地址同样是错误的,因为下面的操作实际是: // 1,申请一段堆内存; // 2,将堆内存的首地址赋给t; // 也就是说,t被重新赋值了,原先传递进来的参数值被抹掉了 t = (Teacher*)malloc(sizeof(Teacher)); t->age = 10; t->name = "hsh";}// 此处操作的是原来地址指向的变量(对其进行初始化)// 可以影响到传递进来的实参void getTeacher3(Teacher *t){ (*t) = { "hsh", 20 };}void main(){ //Teacher *t; // 如果传递给二级指针,则必须传递地址 //getTeacher(&t); // 如果形参是引用,则直接传递变量即可 // t就是一个指针变量,当它传递给一级指针的函数形参时, // 仍然只是值传递,想要达到引用传递的目的,形参必须是一个二级指针或者指针引用 //getTeacher(t); // 报错!!!,指针并没有被初始化 // 并不是说,指针作为形参,传递过去就是引用传递,因为指针本身也可以认为是变量的一种, // 指针要实现引用传递的途径和普通变量是一样的,通过多一级的指针接收或者通过引用形参来接收 //getTeacher2(t); //cout << t->name << t->age << endl; Teacher teacher; // 报错!!!,变量并没有被初始化 // 传递一个没有初始化的首地址作为形参, // 如果函数中使用了动态内存申请来给指针赋值,同样会错误,因为,此时指针指向的地址已经被重新赋值了 //getTeacher2(&teacher); //cout << teacher.name << teacher.age << endl; // 正确!!! // 只是对原来地址指向的变量进行初始化,则可以 getTeacher3(&teacher); cout << teacher.name << teacher.age << endl; system("pause");} 指针常量与常量指针1234567891011void main(){ int a = 1; // 指针常量,指针的常量,不能改变地址的指针,但可以修改它指向的内容 // const修饰的是指针,所以指针内容不能改变,即地址不能改变 int const *p1 = &a; // 常量指针,指向常量的指针,内容不能修改 // const修饰的是变量类型,所以变量类型的内容常量化 const int *p2 = &a;} 常引用1234567891011121314void main(){ int a = 10; int c = 2; // 常引用是不能重新赋值的 const int &b = a; //b = c; // 跟上面是一样的,没区别 int const &d = a; //d = c; //&d = 1; // 固定为右边的字面量,实际就是定义常量 const int &e = 10;}