C++学习笔记——引用

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

1.引用的本质

int a = 10;
int &b = a;
//对b进行操作的本质上是对a进行操作
//a和b指向同一片内存空间
b = 7;
//发现是引用转换为 int* const ref = &a;
void func(int& ref){
    ref = 100; // ref是引用转换为*ref = 100
}
int main(){
    int a = 10;

    //自动转换为 int* const ref = &a; 指针常量是指针指向不可改也说明为什么引用不可更改
    int& ref = a; 
    ref = 20; //内部发现ref是引用自动帮我们转换为: *ref = 20;

    cout << "a:" << a << endl;
    cout << "ref:" << ref << endl;

    func(a);
    return 0;
}

引用的本质为指针常量只能修改指向的值不能修改指向的地址

(1指针常量(指针是常量是一个指向不可改值可改的指针

int a = 10, b = 20;
int * const p = &a;
*p = 30; // p指向的地址是一定的但其内容可以修改

(2常量指针(常量是指针一个指向可改值不可改的指针

int a = 10, b = 20;
const int *p = &a;
p = &b; // 指针可以指向其他地址但是内容不可以改变

(谁先说谁不变谁先说先写谁→*和p 

2.引用的注意事项

1.引用必须初始化

//int &b;是错误的必须对引用进行初始化

2.引用在初始化后不可以改变(引用是指针常量

int &b = a;
b = c;
//这是允许的因为这是赋值操作即将c的值赋值给b而不是修改b的引用对象

3.引用作函数参数

//1. 值传递 
void mySwap01(int a, int b) { 
    int temp = a; 
    a = b; 
    b = temp; 
}

//2. 地址传递 
void mySwap02(int* a, int* b) { 
    int temp = *a; 
    *a = *b; 
    *b = temp; 
}

//3. 引用传递 
void mySwap03(int& a, int& b) { 
    int temp = a; 
    a = b; 
    b = temp; 
}

1.值传递中修改的是形参(传入函数的实参的拷贝属于局部变量只会修改swap函数中的a和b但main函数中的a和b并不会修改

2.地址传递中传入的是main函数中的a和b的地址修改swap函数中的a和b会导致main函数中的a和b发生改变

3.引用传递中swap函数的a和b是main函数中a和b的别名修改swap函数的a和b会导致main函数的a和b发生改变

其中函数里的a和main函数里的a处在不同的局部区域内是不同的局部变量;不是引用名和函数名可以起的一样只是参数的作用空间不一样所以显得可以重名但实际上在一个局部空间里不允许也没必要让引用和原变量重名

4.引用做函数返回值

//返回局部变量引用
int& test01() {
    int a = 10; //局部变量
    return a;
}

//返回静态变量引用
int& test02() {
    static int a = 20;
    return a;
}

int main() {

    //不能返回局部变量的引用
    int& ref = test01();
    cout << "ref = " << ref << endl;
    cout << "ref = " << ref << endl;

    //如果函数做左值那么必须返回引用
    int& ref2 = test02();
    cout << "ref2 = " << ref2 << endl;
    cout << "ref2 = " << ref2 << endl;

    test02() = 1000;

    cout << "ref2 = " << ref2 << endl;
    cout << "ref2 = " << ref2 << endl;

    system("pause");

    return 0;
}

①全局区由操作系统分配释放栈区通过编译器分配释放堆区由用户分配释放

②如果是返回局部变量引用则test01函数结束后返回main函数第一次通过cout输出系统保留该值;第二次则会被系统回收访问越界

③如果是返回静态变量引用则test02函数结束后返回main函数可以通过cout输出该值

④返回引用可以作为左值(因为此时返回的引用是该变量的别名

(1张三有1台手机张三的小名叫伞伞伞伞又去买了1台手机所以张三/伞伞有2台手机

(2把test02理解为是变量a的别名此时取ref2为test02的别名实质上都是返回值a(ref和test02都是a的别名

5.常量引用

①如果采用以下方式引用是错误的;引用必须提供(指向一个合法的地址而10是常量

//int &ref = 10;

②如果采用以下方式引用是正确的;编译器将会先申明一个变量(对程序员透明来存储10然后用ref指向这个变量的地址(可以通过cout输出此地址

//编译器先int temp = 10;
//再const int &p = temp;
const int &p = 10;

③如果要通过引用的方式传入参数为了防止在函数中对参数进行修改可以采用const的方式防止

(1需要首先明确的是形参改变实参这种情况只可能发生在地址传递或引用传递之中(值传递修改的是实参的拷贝

(2“防止形参改变实参”的意思是在函数中可能会对形参的值进行修改;由于是引用传递因此实参也会跟着改变(加了const后在函数中对形参进行修改将会报错

(3引用传递可以有效减少内存占用(主要目的;如果采用值传递的方式虽然改变形参并不会改变实参但是会增加内存占用

//引用使用的场景通常用来修饰形参
void showValue(const int& v) {
    //v += 10;
    cout << v << endl;
}

int main() {

    //int& ref = 10;  引用本身需要一个合法的内存空间因此这行错误
    //加入const就可以了编译器优化代码int temp = 10; const int& ref = temp;
    const int& ref = 10;

    //ref = 100;  //加入const后不可以修改变量
    cout << ref << endl;

    //函数中利用常量引用防止误操作修改实参
    int a = 10;
    showValue(a);

    system("pause");

    return 0;
}
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: c++