GESP 客观题评测系统

试卷解析 · 理解每一步

2025-03-Level-4

2025-03-Level-4

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

单选题

第 1 题(单选题,2 分)

关于下述代码,说法错误的是()。

int multiply(int x, int y);

int main() {
    int a = 4;
    int b = 5;
    int result = multiply(a, b);
    std::cout << "The result is: " << result << std::endl;
    return 0;
}

int multiply(int x, int y) {
    return x * y;
}
A.
函数 multiply 的定义应该放到函数 main 之前。
B.
函数声明 int multiply(int x, int y); 中明确指定了函数 multiply() 的返回值为整数类型。
C.
在 main 函数中,函数 multiply 通过 multiply(a, b) 被调用,其中 a 和 b 是定义在 main 函数中的变量,它们作为实参传递给了 multiply 函数的形参 x 和 y。
D.
运行上述代码,将输出 The result is: 20。

正确答案A

解析详情
答案 A函数声明与定义
思路与推导
  1. 在 C++ 中,如果在 main 函数之前提供了函数声明 int multiply(int x, int y);,那么函数定义可以放在 main 函数之后,程序能正常编译运行。因此,选项 A 说法错误。

第 2 题(单选题,2 分)

执行下述代码将输出()。

int x = 10;
void func() { int x = 20; std::cout << x; }
int main() {
    func();
    std::cout << x;
    return 0;
}
A.
2020
B.
2010
C.
1010
D.
编译错误

正确答案B

解析详情
答案 B变量作用域
思路与推导
  1. func 内部定义了局部变量 x=20,屏蔽了全局变量,输出 20;main 中调用 func 后输出全局变量 x,即 10。最终顺序输出 2010。

第 3 题(单选题,2 分)

执行下述代码后,变量 a 的值为()。

int a = 10;
int* p = &a;
*p = 20
A.
10
B.
20
C.
随机值
D.
编译错误

正确答案B

解析详情
答案 B指针基本操作
思路与推导
  1. 指针 p 指向变量 a 的地址。执行 *p = 20 时,通过指针解引用操作直接修改了 a 所对应内存单元的值。因此 a 变为 20。

第 4 题(单选题,2 分)

以下哪种参数传递方式可以避免拷贝大型对象?

A.
只能用值传递
B.
只能用引用传递
C.
只能用指针传递
D.
引用传递和指针传递均可

正确答案D

解析详情
答案 D参数传递方式
思路与推导
  1. 值传递会创建对象的副本,消耗内存和时间。引用传递和指针传递都只是传递地址或别名,不涉及对象内容的拷贝,是处理大型对象的推荐方式。

第 5 题(单选题,2 分)

执行下述代码,将输出()。

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

int main() {
    int x = 1, y = 2;
    swap(x, y);
    std::cout << x << y;
    return 0;
}
A.
12
B.
21
C.
22
D.
11

正确答案D

解析详情
答案 D值传递与引用传递
思路与推导
  1. swap 函数中第一个参数 a 是值传递,x 的值(1)被拷贝给 a,对 a 的修改不影响 x。第二个参数 b 是引用传递,b 是 y 的别名,对 b 的修改即对 y 的修改。最终 x=1, y=1,输出 11。

第 6 题(单选题,2 分)

下面的描述中,()正确定义一个名为 Person 的结构体并正确初始化了一个 Person 结构体的变量 p 。

A.
struct Person {
    string name;
    int age;
};
Person p("Yang", 10);
B.
struct Person {
    string name,
    int age;
};
Person p;
p.name = "Yang";
p.age = 10;
C.
struct Person {
    string name;
    int age;
};
Person p = { "Yang", 10 };
D.
struct Person {
    string name;
    int age;
};
Person p = new Person("Yang", 10);

正确答案C

解析详情
答案 C结构体定义与初始化
思路与推导
  1. A 选项使用构造函数语法但未定义构造函数;B 选项定义中成员间使用了逗号;D 选项使用了错误的动态内存分配语法。C 选项是标准的列表初始化语法,正确。

第 7 题(单选题,2 分)

给定如下代码,

struct Person {
    std::string name;
    int age;
    struct Address {
        std::string street;
        std::string city;
    };
    Address address;
};

下面描述错误的是()。

A.
结构 Person 内嵌套结构 Address
B.
Person 有一个 Address 类型的 address 成员
C.
一个 Person 类型的变量 p 的 address 的初始化可以写成:p.address.street = "123 Main St"; p.address.city = "Anytown";
D.
结构的嵌套可以减少命名冲突,因此可以不必控制嵌套层次

正确答案D

解析详情
答案 D结构体嵌套
思路与推导
  1. 结构体确实可以嵌套以逻辑化组织数据并减少命名冲突。但过深的嵌套会导致代码臃肿、访问路径过长且难以维护,必须根据实际需求控制嵌套层次。D 选项描述太绝对。

第 8 题(单选题,2 分)

假设 int arr[2][3] = {{1,2,3},{4,5,6}};,则 arr[1][2] 的值是()。

A.
2
B.
3
C.
5
D.
6

正确答案D

解析详情
答案 D二维数组索引
思路与推导
  1. C++ 数组索引从 0 开始。arr[1] 指向第二行 {4, 5, 6},arr[1][2] 指向该行的第三个元素,即 6。

第 9 题(单选题,2 分)

下面()正确定义了二维数组。

A.
int arr[3,4];
B.
int arr[3][4];
C.
int arr(3,4);
D.
int a[3-4];

正确答案B

解析详情
答案 B二维数组定义语法
思路与推导
  1. C++ 二维数组的正确定义语法是 类型 数组名[行数][列数]。A、C、D 选项均不符合 C++ 语法要求。

第 10 题(单选题,2 分)

小杨正在爬楼梯,需要爬 n 阶才能到达楼顶。如果每次可以爬 1 个或 2 个台阶,下面代码采用递推算法来计算一共有多少种不同的方法可以爬到楼顶,则横线上应填写()。

int f(int n) {
    if (n == 1 || n == 2)
        return n;
    
    int f1 = 1;
    int f2 = 2;
    int res = 0;
    for (int i = 3; i <= n; i++) {
        // 在此处填入代码
    }
    return res;
}
A.
res += f1 + f2;
f1 = f2;
f2 = res;
B.
res = f1 + f2;
f1 = f2;
f2 = res;
C.
res += f1 + f2;
f2 = res;
f1 = f2;
D.
res = f1 + f2;
f2 = res;
f1 = f2;

正确答案B

解析详情
答案 B递推算法(斐波那契数列)
思路与推导
  1. 爬楼梯问题符合斐波那契数列递推关系 f(i) = f(i-1) + f(i-2)。在循环中,计算出当前项 res 后,需要将 f1 更新为原 f2,将 f2 更新为 res,为计算下一项做准备。

第 11 题(单选题,2 分)

给定如下算法,其时间复杂度为()。

bool f(int arr[], int n, int target) {
    for (int i = 0; i < (1 << n); i++) {
        int sum = 0;
        for (int j = 0; j < n; j++) {
            if (i & (1 << j)) {
                sum += arr[j];
            }
        }
        if (sum == target) return true;
    }
    return false;
}
A.
O(n2)O(n^{2})
B.
O(n×2n)O(n \times 2^{n})
C.
O(1)O(1)
D.
O(n3)O(n^{3})

正确答案B

解析详情
答案 B时间复杂度分析
思路与推导
  1. 外层循环执行 1 << n 即 2^n 次。内层循环固定执行 n 次。总的操作次数量级为 n * 2^n,因此时间复杂度为 O(n * 2^n)。

第 12 题(单选题,2 分)

下面关于排序稳定性的描述,正确的是()。

A.
稳定性指算法的时间复杂度恒定
B.
稳定排序保证相同元素的相对顺序不变
C.
选择排序是稳定排序
D.
插入排序不是稳定排序

正确答案B

解析详情
答案 B排序算法稳定性
思路与推导
  1. 稳定性是指如果两个元素值相等,排序后它们的相对先后顺序保持不变。选项 B 正确描述了这一概念。选择排序是不稳定的,插入排序是稳定的。

第 13 题(单选题,2 分)

对数组 arr[]={5, 3, 8, 1} 进行升序排序,执行第一轮冒泡排序后数组 arr 中的内容为()。

A.
3, 5, 1, 8
B.
3, 1, 5, 8
C.
3, 5, 8, 1
D.
5, 3, 8, 1

正确答案A

解析详情
答案 A冒泡排序过程分析
思路与推导
  1. 第一轮冒泡排序步骤:1. 比较 5,3 交换得 {3,5,8,1};2. 比较 5,8 不动;3. 比较 8,1 交换得 {3,5,1,8}。此时最大的 8 已被移动到最右侧。

第 14 题(单选题,2 分)

运行下面的代码,将出现()。

double hmean(double a, double b) {
    if (a == -b)
        throw runtime_error("Runtime error occurred.");
    return 2.0*a*b/(a + b);
}

int main() {
    double x = 10;
    double y = -10;
    try {
        int result = hmean(x, y);
        cout << "hmean: " << result << endl;
    }
}
catch (const runtime_error& e) {
    cout << "Caught: " << e.what() << endl;
} catch (...) {
    cout << "Caught an unknown exception." << endl;
}
return 0;
A.
屏幕上输出 Caught: Runtime error occurred.
B.
屏幕上输出 Caught an unknown exception.
C.
程序调用 std::terminate()
D.
编译错误

正确答案A

解析详情
答案 AC++ 异常处理机制
思路与推导
  1. 代码中 x=10, y=-10 满足 a == -b,hmean 抛出 runtime_error 异常。main 函数中的 try-catch 块捕获了该特定类型的异常并输出 Caught: ... 内容。

第 15 题(单选题,2 分)

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

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

正确答案C

解析详情
答案 C文件重定向与输入输出流
思路与推导
  1. A 使用 freopen 重定向 stdout,B 直接向文件流输出,D 通过 rdbuf 修改 cout 绑定。C 选项虽然打开了文件流但未对 cout 做任何处理,cout 依然输出到标准设备。

判断题

第 1 题(判断题,2 分)

函数是C++中的核心概念,用于封装可重用的代码块。

正确答案正确

解析详情
答案 正确函数基本概念
思路与推导
  1. 函数是 C++ 等结构化编程语言的核心组成部分,通过定义函数可以实现逻辑封装、降低复杂度并提高代码复用性。

第 2 题(判断题,2 分)

在C++中,函数的返回类型可以省略,默认为 int。

正确答案错误

解析详情
答案 错误函数定义语法规范
思路与推导
  1. 在现代 C++ 标准中,函数定义和声明必须明确指出返回类型。虽然早期的 C 语言可能支持默认 int,但 C++ 从未正式允许这种用法。

第 3 题(判断题,2 分)

结构体的成员默认是 public 访问权限。

正确答案正确

解析详情
答案 正确结构体与类的访问权限区别
思路与推导
  1. 在 C++ 中,struct 的成员默认访问权限是 public,而 class 的成员默认访问权限是 private。这是两者唯一的本质区别。

第 4 题(判断题,2 分)

假设整数数组 arr[4] = {0, 1, 2, 3}; 的第一个元素在内存中的地址为 0x7ffee4065820,经过 int* p = arr; p += 1;后,指针 p 的值是1。

正确答案错误

解析详情
答案 错误指针运算与内存地址
思路与推导
  1. 执行 p += 1 后,指针 p 存储的地址值会增加一个 int 类型的偏移量(通常是 4 字节),而非变成数值 1。p 的值依然是一个内存地址。

第 5 题(判断题,2 分)

二维数组作为函数参数时,必须显式指定所有维度的大小。

正确答案错误

解析详情
答案 错误多维数组作为函数参数
思路与推导
  1. 二维数组传参时,必须指定除第一维以外的所有维度的大小。第一维的大小可以省略,由编译器根据后续维度推导寻址逻辑。

第 6 题(判断题,2 分)

递推是一种通过已知的初始值和递推公式,逐步求解目标值的算法。

正确答案正确

解析详情
答案 正确递推算法定义
思路与推导
  1. 递推算法通过确定的状态转移方程,从初始状态(边界条件)出发迭代计算到目标状态,是解决动态规划等问题的常用手段。

第 7 题(判断题,2 分)

考虑最坏情况下冒泡排序算法的时间复杂度,T(n)T(n)为待排序数字的数目为n的复杂度,则其递推关系式为T(n)=T(n−1)+nT(n)=T(n-1)+n,T(0)=1T(0)=1。

正确答案正确

解析详情
答案 正确冒泡排序算法复杂度分析
思路与推导
  1. 冒泡排序最坏情况下,每轮需要完成 n 次比较操作来固定一个元素,因此 T(n) = T(n-1) + n。展开后即为等差数列求和,复杂度为 O(n^2)。

第 8 题(判断题,2 分)

插入排序在最好情况(已有序)下的时间复杂度是O(n2)O(n^{2})。

正确答案错误

解析详情
答案 错误插入排序算法复杂度
思路与推导
  1. 插入排序在已有序的情况下,每轮只需进行 1 次比较且无需移动元素,总的时间复杂度降为 O(n)。

第 9 题(判断题,2 分)

对数组 arr[] = {4, 3, 1, 5, 2} 进行升序排序,执行第一轮选择排序后数组arr中的内容是 {1, 4, 3, 5, 2}。

正确答案错误

解析详情
答案 错误选择排序过程分析
思路与推导
  1. 选择排序第一轮:在全序列中找到最小值 1,与首元素 4 交换。结果序列应为 {1, 3, 4, 5, 2}。题干中 3 和 4 的位置不对。

第 10 题(判断题,2 分)

未捕获异常会调用std::terminate终止程序。

正确答案正确

解析详情
答案 正确C++ 异常处理生命周期
思路与推导
  1. 如果程序中抛出的异常没有被任何匹配的 catch 块捕获,或者在处理异常的过程中又产生新异常,系统会调用 std::terminate() 立即终止程序运行。