• C++ 引用和指针


    引用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // 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");
    }

    引用传递

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    // 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");
    }

    指针引用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58大专栏  C++ 引用和指针pan>
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    void 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");
    }

    指针常量与常量指针

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void main(){
    int a = 1;

    // 指针常量,指针的常量,不能改变地址的指针,但可以修改它指向的内容
    // const修饰的是指针,所以指针内容不能改变,即地址不能改变
    int const *p1 = &a;

    // 常量指针,指向常量的指针,内容不能修改
    // const修饰的是变量类型,所以变量类型的内容常量化
    const int *p2 = &a;
    }

    常引用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    void 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;
    }
  • 相关阅读:
    SqlServer 格式化时间
    工作生活两三事
    前端面试题准备 3
    前端面试题准备 2
    MYSQL---自定义函数
    MYSQL---MD5()、PASSWORD()函数
    MYSQL---DATE_ADD()
    MYSQL---%
    MYSQL---多表删除
    MYSQL---CREATE...SELECT
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12433017.html
Copyright © 2020-2023  润新知