#CPP7. 【Level 0】引用

【Level 0】引用

引用

  我们应当尽可能使用引用而不使用指针,即使迫不得已,也请使用智能指针

  引用其实就是一个别名,所以要与被引用的变量具有相同的类型,用& 名称表示引用,例如

int i = 10;
int &r = i;

  此时,ri的值都是10,可以尝试修改ri,发现它们的值会被同时修改:

int i = 10;
int &r = i;
cout << i << " " << r << endl;
i = 9;
cout << i << " " << r << endl;
r = 11;
cout << i << " " << r << endl;

  输出的结果为

10 10
9 9
11 11

1 简化代码

  用一个变量去代替另一个变量看似没有意义,因此我们先介绍它在简化代码方面的作用。

  观察如下代码:

vector<vector<int>> a;

int x, y;
x = a[i - 2*j + 1][0] + a[i - 2*j + 1][1];
y = a[i - 2*j + 1][2] + a[i - 2*j + 1][3];

  可以看到,这样代码有大量复杂的重复内容,而a[i - 2*j + 1]实际上就是一个vector<int>,因此我们可以声明它的引用以简化代码

vector<int> &ax = a[i - 2*j +1];

int x, y;
x = ax[0] + ax[1];
y = ax[2] + ax[3];

2 swap()的实现

  假设需要实现一个swap函数,其作用是交换输入的两个变量的值,我们有:

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

  然而,在我们调用之后,发现变量的值并没有被交换

int x = 3, y = 5;
swap(x, y);
cout << x << " " << y << endl;

  这是由于这样的函数,传递的实际上是值。相当于在函数的位置新建了两个变量ab,将xy的值分别赋给ab,那么这样一来,我们在swap()里的交换,就对于函数外部的xy不起作用。

  要想实现交换的效果,就需要引用。这时ab就相当于xy的别名,从而指向同一块内存空间

void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}
int x = 3, y = 5;
swap(x, y);
cout << x << " " << y << endl;

  这样,我们就可以看到xy的值被交换了。

3 减少拷贝

  我们在学习二维vector时,提到vec1和vec2放进nums后,vec1、vec2与nums无关,即改变vec1内的值,并不能改变nums内的值

  这实际上就是因为,push_back()就是在将vec1的值拷贝一份到nums中。

  而如果我们的函数参数中含有vector等数据结构,自然也会遇到这样的问题,例如:

void print_vec(vector<int> x) {
    int size = x.size();

    for (int i = 0; i < size; i++) {
        cout << x[i] << " ";
    }
    cout << endl;
}

int main() {
    vector<int> vec = {1, 3, 5, 7, 9};
    print_vec(vec);
}

  我们想要实现的功能是输出vector中的所有值,这个函数也能够实现,但接下来我们需要考虑拷贝的问题。

  从前文我们已经知道,在传递参数时要把变量的值拷贝一份,那么自然,传入的vector也要把整个vector的数据拷贝一份,这是很耗时而且无意义的。

  所以,我们只需要使用引用,就可以节省拷贝整个vector的时间,对于任何很大的数据结构都可以这样操作:

void print_vec(vector<int> &x) {
    int size = x.size();

    for (int i = 0; i < size; i++) {
        cout << x[i] << " ";
    }
    cout << endl;
}

  你可以对比,在 vector 中数据量很大时,调用这两种实现函数的开销。

  最后值得一提的是,如果你仅仅为了减少拷贝而不希望变量被修改,可以声明为 const,将其变为 常量引用

void print_vec(const vector<int> &x)
...

Description

  n(n100)n(n\le 100) 名同学参加歌唱比赛,并接受 m(m20)m(m\le 20) 名评委的评分,评分范围是 001010 分。这名同学的得分就是这些评委给分中去掉一个最高分,去掉一个最低分,剩下 m2m-2 个评分的平均数。请问得分最高的同学分数是多少?

  请先引用一个头文件

#include "TopStudent.h"

  然后编写一个函数,其名称为topStudent。传入的参数类型为 vector<vector<int>>常量引用,这个 vector 中共有 nn 行,每行有 mm 个值,代表 mm 个评委对于该同学的分数。返回值是 double 类型,得分最高的同学的分数。

  注意,提交时仅提交头文件+topStudent函数,形如

#include "TopStudent.h"

你的函数

Notes

  虽然本题 不需要输入输出,但提供一组样例用于自测模式

5 5
9 2 1 3 4
8 2 7 1 5
4 3 8 1 6
4 9 2 1 3
6 5 5 6 5
5.33