GESP 客观题评测系统

2026-03-Level-4

2026-03-Level-4

试卷解析总览,可直接查看每题答案与解析。

单选题(每题 2 分)

1 题(单选题

执行下面程序后,输出为()。

int f(int x = 2){
    return x * 3;
}

int main(){
    cout << f() << " " << f(4);
}
A.
2 12
B.
6 12
C.
6 4
D.
12 6

正确答案B

解析详情

【答案】B

【考点】函数默认参数

【解析】 函数 f 具有默认参数 x=2。在 main 函数中,第一次调用 f() 使用默认值,返回 2*3=6;第二次调用 f(4) 显式传入 4,返回 4*3=12。因此输出结果为 6 12。

【易错点】 误认为调用无参函数 f() 会导致编译错误,或忽略默认参数的乘法计算。

2 题(单选题

执行下面代码后,输出为()。

int main() {
    int a = 5;
    int* p = &a;
    int** q = &p;
    **q += 7;
    cout << a << " " << *p;
}
A.
5 5
B.
12 12
C.
12 5
D.
5 12

正确答案B

解析详情

【答案】B

【考点】多级指针与间接访问

【解析】 p 指向变量 a,q 是指向 p 的二级指针。表达式 **q 等价于 *p,最终指向变量 a 本身。执行 **q += 7 即 a += 7,使 a 的值变为 12。由于 *p 也指向 a,因此输出 a 和 *p 均为 12。

【易错点】 未能理清多级指针的解引用层次,误认为修改 **q 不会影响 a 或 *p 的输出。

3 题(单选题

已知:

int a[3][4] = {
    {1,2,3,4},
    {5,6,7,8},
    {9,10,11,12}
};
int (*p)[4] = a;

则表达式 *(*(p + 2) + 1) 的值为()。

A.
6
B.
10
C.
9
D.
11

正确答案B

解析详情

【答案】B

【考点】二维数组与数组指针

【解析】 p 是指向含有 4 个整数数组的指针。p + 2 指向二维数组的第三行(即子数组 {9,10,11,12})。*(p + 2) 得到该行的起始地址。*(p + 2) + 1 指向该行第二个元素的地址,解引用后得到 a[2][1] 的值,即 10。

【易错点】 对数组指针 p 的偏移计算不熟练,误认为 p + 2 指向的是元素级别而非行级别。

4 题(单选题

执行下面程序后,输出为()。

void fun(int a, int &b, int *c){
    a += 1;
    b += 2;
    *c += 3;
}

int main(){
    int x = 1, y = 1, z = 1;
    fun(x, y, &z);
    cout << x << " " << y << " " << z;
}
A.
2 3 4
B.
1 3 4
C.
2 1 4
D.
1 1 1

正确答案B

解析详情

【答案】B

【考点】函数参数传递方式

【解析】 x 传值给 a,函数内修改不影响原变量;y 传引用给 b,修改 b 使 y 变为 1+2=3;z 传指针地址给 c,修改 *c 使 z 变为 1+3=4。最终输出 x y z 分别为 1 3 4。

【易错点】 误认为传值调用(x 到 a)也会修改原变量,导致首个数字误选为 2。

5 题(单选题

执行下面程序后输出为()。

int x = 3;
void f(int& x){
    x += 2;
}
int main(){
    int x = 10;
    f(x);
    cout << x << " " << ::x;
}
A.
12 3
B.
10 5
C.
12 5
D.
10 3

正确答案A

解析详情

【答案】A

【考点】变量作用域与全局标识符

【解析】 main 函数内的局部变量 x (10) 屏蔽了全局变量 x (3)。调用 f(x) 传入的是局部变量 x 的引用,修改后局部变量变为 12。::x 显式指明访问全局作用域中的 x,其值仍为 3。因此输出 12 3。

【易错点】 误认为 f(x) 修改的是全局变量,或者混淆了 ::x 与普通 x 的指向。

6 题(单选题

下列关于结构体初始化的写法,正确的是()。

A.
struct Point { int x, y; };
Point p = (1,2);
B.
struct Point { int x, y; };
Point p = {1,2};
C.
struct Point { int x, y; };
Point p = new Point(1,2);
D.
struct Point { int x, y; };
Point p = <1,2>;

正确答案B

解析详情

【答案】B

【考点】结构体初始化

【解析】 在 C++ 中,结构体可以通过大括号 {} 进行列表初始化。选项 B 的 Point p = {1, 2} 是标准的初始化语法。选项 A 使用圆括号会被解释为逗号表达式;选项 C 的 new 语法用于动态内存分配且应赋值给指针;选项 D 使用 <> 不符合语法。

【易错点】 混淆结构体变量声明与构造函数调用,或对列表初始化语法记忆不牢。

7 题(单选题

执行下面代码后输出为()。

struct S { int a; int b; };

void g(S s){ s.a += 10; }
void h(S& s){ s.b += 10; }

int main(){
    S s{1,2};
    g(s);
    h(s);
    cout << s.a << " " << s.b;
}
A.
11 12
B.
1 12
C.
11 2
D.
1 2

正确答案B

解析详情

【答案】B

【考点】结构体参数传递(传值 vs 传引用)

【解析】 g(s) 是传值调用,函数内对 s.a 的修改只影响局部副本,不影响 main 中的原变量;h(s) 是传引用调用,对 s.b 的修改直接作用于 main 中的 s。最终输出 s.a=1, s.b=2+10=12。

【易错点】 误认为结构体作为参数时默认总是按引用传递,导致错误地认为 a 的值也会改变。

8 题(单选题

关于递推算法的描述,正确的是()。

A.
递推表现为函数自己调用自己
B.
递推从已知初值出发,利用递推关系逐步推出后续结果
C.
递推只能用于指数复杂度问题
D.
递推一定需要回溯

正确答案B

解析详情

【答案】B

【考点】递推算法定义与特征

【解析】 递推算法的核心是从已知的边界条件(初值)出发,通过确定的递推公式逐步求解后续项。函数调用自身是递归;递推不强制要求回溯;递推常用于多项式时间问题(如斐波那契、动态规划等)。

【易错点】 混淆递推(从已知向未知推导)与递归(从目标向下层拆分)的概念。

9 题(单选题

执行 climb(6) 的返回值为()。

int climb(int n){
    if(n <= 2) return n;
    int a = 1, b = 2, c = 0;
    for(int i = 3; i <= n; i++) {
        c = a + b;
        a = b;
        b = c;
    }
    return c;
}
A.
8
B.
13
C.
5
D.
10

正确答案B

解析详情

【答案】B

【考点】循环递推与斐波那契数列

【解析】 此程序模拟爬楼梯问题,即 f(n)=f(n-1)+f(n-2)。初始 f(1)=1, f(2)=2。循环计算:i=3, c=3, a=2, b=3;i=4, c=5, a=3, b=5;i=5, c=8, a=5, b=8;i=6, c=13。最终返回 13。

【易错点】 由于该数列起始值为 1, 2,而非标准斐波那契的 1, 1,容易因套用习惯公式导致结果偏移一位。

10 题(单选题

某排序算法对如下数据排序(按 score 升序),则下面关于该排序算法稳定性的描述中,说法正确的是()。初始:(90,'A'),(90,'B'),(80,'C'),(90,'D')排序后:(80,'C'),(90,'A'),(90,'B'),(90,'D')

A.
不稳定,因为出现了相同分数
B.
稳定,因为相同 score 的相对顺序保持为 A 在 B 前、B 在 D 前
C.
不稳定,因为 C 跑到前面了
D.
无法判断

正确答案B

解析详情

【答案】B

【考点】排序算法的稳定性

【解析】 稳定性是指如果两个元素关键字相同,排序后它们的相对先后顺序保持不变。在本题中,分数为 90 的三个元素 A、B、D 在排序后的相对顺序依然是 A 在前、B 在中、D 在后,符合稳定性定义。

【易错点】 误认为只要元素发生了移动就是“不稳定”,忽略了“相对顺序”这一核心判断标准。

11 题(单选题

下面代码试图把数组按升序进行“插入排序”,横线处应填写()。

void ins(int a[], int n){
    for(int i = 1; i < n; i++) {
        int key = a[i];
        int j = i - 1;
        while (j >= 0 && _____){
            a[j + 1] = a[j];
            j--;
        }
        a[j + 1] = key;
    }
}
A.
a[j] < key
B.
a[j] > key
C.
a[j + 1] > key
D.
a[j] == key

正确答案B

解析详情

【答案】B

【考点】插入排序算法实现

【解析】 在升序插入排序中,需要将当前待插入值 key 与前面已排序部分的元素逐一比较。若 a[j] 大于 key,则应将 a[j] 向后搬移一位为 key 腾出空间,因此 while 循环的条件是 a[j] > key。

【易错点】 误选 a[j] < key 导致程序执行降序排序,或者混淆了 j 与 j+1 的下标含义。

12 题(单选题

下列代码段的时间复杂度为()。

int cnt=0;
for(int i=0; i<n; i++) {
    for(int j=0; j<n; j++) {
        if((i+j) % 3 == 0) cnt++;
    }
}
A.
O(n)O(n)
B.
O(nlogn)O(n \log n)
C.
O(n2)O(n^2)
D.
O(2n)O(2^n)

正确答案C

解析详情

【答案】C

【考点】时间复杂度分析(双重循环)

【解析】 外层循环从 0 到 n-1 执行 n 次,内层循环同样从 0 到 n-1 执行 n 次。循环体内是常数时间的操作。总的基本操作执行次数为 n * n = n^2,故时间复杂度为 O(n^2)。

【易错点】 忽略嵌套循环的乘积关系,或者错误地认为 if 语句中的取模操作会改变复杂度级别。

13 题(单选题

下面哪种方式不能实现将字符串 Welcome to 2026!输出重定向到文件 log.txt()。

A.
freopen("log.txt", "w", stdout);
cout << "Welcome to 2026!" << endl;
fclose(stdout);
B.
std::ofstream outFile("log.txt");
cout << "Welcome to 2026!" << endl;
outFile.close();
C.
ofstream log_file("log.txt");
streambuf* org_cout = cout.rdbuf();
cout.rdbuf(log_file.rdbuf());
cout << "Welcome to 2026!" << endl;
cout.rdbuf(org_cout);
D.
std::ofstream outFile("log.txt");
outFile << "Welcome to 2026!" << endl;
outFile.close();

正确答案B

解析详情

【答案】B

【考点】C++ 输出重定向与文件流操作

【解析】 选项 B 中,虽然定义了 outFile,但 cout 依然指向标准输出(屏幕)。程序随后执行 cout << ...,内容依然会显示在控制台而非写入文件。选项 A (freopen)、C (rdbuf) 均实现了 cout 的重定向,选项 D 则是直接使用文件流写入。

【易错点】 看到 ofstream 就误认为会自动重定向 cout,忽略了重定向需要显式修改输出流的目标缓冲区。

14 题(单选题

执行下面程序,输出结果是()。

int divi(int a,int b){
    if(b==0) throw 0;
    return a/b;
}

int main(){
    try{
        cout << divi(10,0);
    }catch(const char* msg){
        cout << "A";
    }catch(int){
        cout << "B";
    }
}
A.
A
B.
B
C.
程序崩溃
D.
无输出

正确答案B

解析详情

【答案】B

【考点】异常处理(try-catch 机制)

【解析】 divi(10, 0) 检测到除数为 0,抛出一个整数异常 throw 0。在 main 函数的 try 块中,该异常会被 catch(int) 分支捕获,并输出 "B"。catch(const char*) 只处理字符串类型的异常。

【易错点】 混淆不同数据类型的异常匹配规则,或误认为除以 0 抛出的异常会导致程序直接崩溃。

15 题(单选题

下列函数实现排行榜中单个元素的位置调整(类似插入排序的相邻搬移)。当某玩家分数增加,需将其向前移动时,while 循环的条件应为()。

struct Player{ int score; };
void up(Player players[], int n, int idx){
    Player cur = players[idx];
    int i = idx;
    while( _____ ) {
        players[i] = players[i-1];
        i--;
    }
    players[i] = cur;
}
A.
i > 0 && cur.score > players[i-1].score
B.
i > 0 && cur.score < players[i-1].score
C.
i < n-1 && cur.score > players[i+1].score
D.
i < n-1 && cur.score < players[i+1].score

正确答案A

解析详情

【答案】A

【考点】插入排序逻辑应用

0 解析】 将玩家向前移动(下标减小方向),需要保证下标 i > 0 且当前玩家分数 cur.score 大于前一个位置玩家的分数 players[i-1].score,此时才将前一个玩家后移。因此条件为 i > 0 && cur.score > players[i-1].score。

【易错点】 边界条件(i > 0)判断错误,或者分不清应该与 i-1 还是 i+1 比较。

判断题(每题 2 分)

1 题(判断题

下面代码执行结束时,变量 a 的值变成 15。

void add10(int &x) { x += 10; }

int main() {
    int a = 5;
    add10(a);
}

正确答案正确

解析详情

【答案】正确

【考点】引用传递

【解析】 add10 函数参数为 int &x(引用传递),函数内部对 x 的修改会同步反映到实参 a 上。a 的初始值为 5,执行加 10 后变为 15。

【易错点】 误将引用传递看作值传递,从而认为 a 的值保持 5 不变。

2 题(判断题

引用一旦绑定某个变量,就不能再绑定其他变量。()

正确答案正确

解析详情

【答案】正确

【考点】引用基本性质

【解析】 在 C++ 中,引用必须在定义时初始化,且初始化后不能更改其所绑定的对象。后续对引用的赋值只是修改被引用变量的值,而非改变引用本身的绑定关系。

【易错点】 将引用与指针混淆,误以为引用可以像指针一样随时指向不同的内存地址。

3 题(判断题

执行下面代码,输出结果为 5。

int main() {
    int a[2][3];
    cout << &a[1][2] - &a[0][1] << endl;
    return 0;
}

正确答案错误

解析详情

【答案】错误

【考点】二维数组地址计算与指针减法

【解析】 二维数组 a[2][3] 中,每行有 3 个元素。a[1][2] 的线性位置是 1*3+2=5,a[0][1] 的位置是 0*3+1=1。指针相减结果为它们之间相隔的元素个数,即 5-1=4,而非 5。

【易错点】 行偏移量计算错误,或误以为指针减法返回的是字节差。

4 题(判断题

下面程序可以正常编译并输出 10 。

int calc(int x, int y = 10);
int calc(int x) { return x * 2; }
int calc(int x, int y) { return x * y; }

int main() {
    cout << calc(5);
}

正确答案错误

解析详情

【答案】错误

【考点】函数重载与默认参数的冲突

【解析】 程序中同时存在 calc(int) 和带有默认参数的 calc(int, int=10)。调用 calc(5) 时,编译器无法确定是调用第一个版本还是第二个版本的省略形式,存在二义性冲突,导致编译失败。

【易错点】 忽略了默认参数在重载匹配时带来的二义性问题。

5 题(判断题

下面程序执行后输出 2010 。

int x = 10;
void f() { int x = 20; cout << x; }

int main() {
    f();
}

正确答案正确

解析详情

【答案】正确

【考点】变量屏蔽与局部变量优先

【解析】 全局变量 x = 10。在函数 f 内部定义了同名局部变量 x = 20,这会屏蔽掉全局变量。执行 f() 时输出的是局部变量的值 20。由于 main 没其他输出,最终结果就是 20。

【易错点】 误认为全局变量具有最高优先级,或忽略了局部变量对同名全局变量的遮蔽效应。

6 题(判断题

在 C++ 中,如果声明了一个指针变量但没有显式初始化,该指针会自动被初始化为 nullptr。

正确答案错误

解析详情

【答案】错误

【考点】变量初始化规则

【解析】 在 C++ 中,局部非静态变量(包括指针)在声明时如果没有初始化,其初始值是未定义的随机值(垃圾值)。只有全局变量或静态变量才会自动初始化为 0 (nullptr)。

【易错点】 习惯了 Java 等语言的自动零初始化机制,误以为 C++ 的局部变量也会自动赋初值。

7 题(判断题

下面代码没有语法错误。

struct GameCharacter {
    string name;
    int level;
    float position_x;
    float position_y;
    struct Equipment {
        string weapon;
        int attack_bonus;
        int defense_bonus;
    } equipment;
    struct Skill {
        string name;
        int damage;
    } skills[8];
    int skill_count;
};

正确答案正确

解析详情

【答案】正确

【考点】嵌套结构体定义

【解析】 C++ 允许在一个结构体内部定义并实例化其他结构体,这在处理多级复杂数据(如角色的装备、技能数组)时是标准做法,语法完全合法。

【易错点】 误认为必须先在外部定义子结构体,不能在内部直接嵌套定义。

8 题(判断题

下面程序能够把 Hello 写入 data.txt 文件中。

ofstream fout("data.txt");
cout << "Hello";
fout.close();

正确答案错误

解析详情

【答案】错误

【考点】文件流输出操作

【解析】 程序虽然创建了指向文件的 fout 流,但第二行使用的是 cout << "Hello",这将内容输出到了标准控制台而非文件。要写入文件应使用 fout << "Hello"。

【易错点】 误认为只要定义了 fout,后续所有的 cout 内容都会被自动重定向到该文件流中。

9 题(判断题

由于选择排序和插入排序的时间复杂度均为 O(n^{2}) ,在任何实际场景下两者的性能表现几乎相同,可以互相替代。

正确答案错误

解析详情

【答案】错误

【考点】排序算法性能特性对比

【解析】 虽然最坏复杂度相同,但插入排序是稳定的且在处理“几乎有序”数据时效率接近 O(n),而选择排序是不稳定的且无论数据状况如何始终执行 n^2 次比较。两者在实际场景表现差异巨大。

【易错点】 片面相信 O 复杂度,忽略了算法的稳定性及对数据敏感性的差异。

10 题(判断题

下面用递推方式计算斐波那契数列第 n 项的程序,时间复杂度是 O(2^{n}) 。

int fib(int n) {
    if (n <= 1) return n;
    int f0 = 0, f1 = 1, cur = 0;
    for (int i = 2; i <= n; i++) {
        cur = f0 + f1;
        f0 = f1;
        f1 = cur;
    }
    return cur;
}

正确答案错误

解析详情

【答案】错误

【考点】算法复杂度分析(迭代 vs 递归)

【解析】 该程序采用单层循环(迭代方式)计算斐波那契数列,执行次数随 n 线性增长,复杂度为 O(n)。只有不带备忘录的简单递归实现才是 O(2^n)。

【易错点】 对斐波那契数列的常见复杂度印象过于死板,未能区分代码中具体的迭代实现逻辑。