c++的引用

#include <iostream>

using namespace std;

//引用的本质就是同一个变量/空间的另一个名称,与它本来的名称代表的东西是完全一样的
//引用的本质是一个常指针,int *const p = NULL(常量化的变量一定要初始化
//引用的特点
//1.引用没有定义,是一种关系型声明,不分配内存,与被引用的变量有相同的地址
//2.引用声明的时候必须初始化,与一块空间绑定后,永不变更
//3.可以对引用再次引用,多次引用的结果就是某一变量具有多个别名,这些别名就是指这个变量
//4.&符号前有数据类型时才是引用(例int &a,char &b等),其他皆为取地址(&符号在等号左边且&符号左边有数据类型才是引用,const修饰看右边且只看一个对象,右边是谁就修饰谁)

void change_value1(int *p)//int *p = &a
{
    *p = 1000;
}

void change_value2(int &p)//int &p = a
{
    p = 10000;
}

void swap(int &a, int &b)
{
    int temp;
    temp = a;
    a = b;
    b = temp;
}

struct student
{
    char name[64];
    int id;
};
//引用传递比地址传递好,地址传递比值传递好
//地址传递
void my_copy1(student *t)//student *t = &t
{
    cout << t->name << " " << t->id << endl;
}
//引用传递
void my_copy2(student &t)//student &t = t
{
    cout << t.name << " " << t.id << endl;
}
//值传递
void my_copy3(student t)//student t = t
{
    cout << t.name << " " << t.id << endl;
}

//结构体的功能很强大,里面存储的是类型,可以取引用类型
struct A
{
    int &a;
};
struct B
{
    int *a;
};
void function1()
{
    
    cout << "A=" << sizeof(A) << endl;
    cout << "B=" << sizeof(B) << endl;
    //b为a的引用,求b变量大小即为求a的大小,即sizeof(a),所以结果为1
    char a = '1';
    char &b = a;
    cout << "&b=" << sizeof(b) << endl;
}

void motify1(int *const a)//int *const a = &a,常指针a的指向不可以改变,但指向的内容可以改变,常指针也是在常量区的,不是在栈区,但是常指针指向的内容可以是栈区,此时指向的内容时可以改变的,但常指针指向不可改变
{
    *a = 100;
    cout << "a=" << *a << endl;
}
void motify2(int &a)//int &a = a,这与上面是完全一样的,引用的本质就是常指针,当我们函数参数为引用时,编译器会帮我们取实参的地址,而不是值
{
    a = 1000;
    cout << "a=" << a << endl;
}

//函数返回值为引用或变量本身时,return的都是这个变量本身,只是在返回值类型的定义时有区别,其他完全相同
//函数返回值为局部变量的引用时
int &get_value1()
{
    int value = 300;
    return value;
}
//函数返回值为局部变量时
int get_value2()
{
    int value = 400;
    return value;
}
//函数返回值为静态变量/全局变量引用时,函数可以作为左值
int &get_value3()
{
    static int value = 1;//静态变量只初始化一次
    return value;
}

struct teacher
{
    char name[64];
    int id;
};
//函数参数为指针的引用(相当于二级常量指针),对tp操作就相当于对指针本身进行操作,即可以改变指针指向的地址
int get_memory(teacher * &tp)
{
    tp = (teacher *)malloc(sizeof(teacher));
    if (tp == NULL)
    {
        return -1;
    }
    //tp在这儿指的是指针的引用,指针的引用即为指针的别名,所以tp即为指针
    tp->id = 9;
    strcpy_s(tp->name, strlen("xuhaoxuan") +1, "xuhaoxuan");
    return 0;
}

//const修饰函数参数
//1.const修饰普通变量时,表示在这个函数作用域中,a的值不可以更改
int func1(const int a)
{
    return 0;
}
//2.const修饰引用时,表示在这个函数作用中,a的值不可更改(a代表的区域也不可以更改,其实也就是a为变量的别名)
int func2(const int &a)
{
    return 0;
}
//3.const修饰指针指向空间的内容,表示这个指针指向空间的内容不可以改变,但指针的指向可以改变
int func3(const int *a)
{
    int b = 1;
    a = &b;
    return 0;
}
//4.const修饰指针本身,即这个指针的指向不可以改变,但这个指针指向空间的内容可以改变
int func4(int *const a)
{
    *a = 20;
    return 0;
}

int main()
{
    int a = 10;
    int b = 20;

    //指针,是会为指针开辟一个空间,这个空间指向变量a,且可以对指向的空间进行操作
    int *p = &a;
    *p = 100;
    cout << "a=" << a << endl;

    //引用,不会为引用开辟一个空间,一个变量引用另一个变量,相当于为另一个变量取了一个别民,两个变量名都是指完全一样的空间,且对别名操作等同于对原始变量操作
    int &q = b;
    q = 200;
    cout << "b=" << b << endl;
    int &q1 = q;
    q1 = 2000;
    cout << "b=" << b << endl;

    change_value1(&a);
    cout << "a=" << a << endl;
    change_value2(a);
    cout << "a=" << a << endl;

    a = 10, b = 20;
    swap(a, b);
    cout << "a=" << a << endl;
    cout << "b=" << b << endl;

    //结构体初始化时字符串可以直接赋值,后面如果需要对字符串赋值时需要运用拷贝函数
    student t = { "xuhaoxuan",16 };
    my_copy1(&t);
    my_copy2(t);
    my_copy3(t);

    function1();

    motify1(&a);
    motify2(a);

    int value;
    //1.当返回局部变量引用时,必须要用另外一个变量本身区接
    value = get_value1();
    //2.当用引用去接局部变量的引用时,是非常错误的,因为局部变量会消失,你引用的本身空间是不存在的
    //即不能去引用局部变量或局部变量的引用,即那些会销毁的局部区域
    //最好的避免方法即返回值不应为局部变量
    //int &value = get_value1();
    //int &value = get_value2();
    cout << "value=" << value << endl;

    get_value3() = 1000;
    cout << "get_value3()=" << get_value3() << endl;

    teacher *tp;
    get_memory(tp);

    //1.对一个常量进行引用,必须是一个const引用,因为常量是不可改变的,你用一般引用去引用常量,这个引用即为这个常量的别名,那通过这个引用别名就可以改变常量的值了,所以是错误的
    //也可以这样理解,首先int &re引用的本质即为常指针了,这只是说明引用指向的空间不可以改变,但指向空间的内容可以改变,所以再加一个const修饰引用指向空间的内容不可改变
    //错误例子:int &re1 = c;
    const int c = 1;
    const int &re1 = c;
    //2.对一个普通变量进行const引用却是可以的,首先引用本身时常指针,这说明re只能指向空间d,但用const修饰了引用,说明不可以通过引用改变d空间的内容,但可以通过d本身来改变d空间的内容
    int d = 2;
    const int &re2 = d;
    cout << "d=" << d << endl;
    cout << "re2=" << re2 << endl;
    d = 3;
    cout << "d=" << d << endl;
    cout << "re2=" << re2 << endl;
    
    int e = 10;
    func1(e);
    func2(e);
    func3(&e);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值