GESP 客观题评测系统
2025-03-Level-4
2025-03-Level-4
试卷解析总览,可直接查看每题答案与解析。
第 1 题(单选题)
关于下述代码,说法错误的是()。
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
解析详情
【答案】A
【考点】函数声明与定义
【解析】 在 C++ 中,如果在 main 函数之前提供了函数声明 int multiply(int x, int y);,那么函数定义可以放在 main 函数之后,程序能正常编译运行。因此,选项 A 说法错误。
【易错点】 误认为函数定义必须在调用前,忽略了前置声明的作用。
第 2 题(单选题)
执行下述代码将输出()。
int x = 10;
void func() { int x = 20; std::cout << x; }
int main() {
func();
std::cout << x;
return 0;
}正确答案B
解析详情
【答案】B
【考点】变量作用域
【解析】 func 内部定义了局部变量 x=20,屏蔽了全局变量,输出 20;main 中调用 func 后输出全局变量 x,即 10。最终顺序输出 2010。
【易错点】 混淆局部变量和全局变量的作用范围,或者误认为 func 修改了全局变量。
第 3 题(单选题)
执行下述代码后,变量 a 的值为()。
int a = 10;
int* p = &a;
*p = 20正确答案B
解析详情
【答案】B
【考点】指针基本操作
【解析】 指针 p 指向变量 a 的地址。执行 *p = 20 时,通过指针解引用操作直接修改了 a 所对应内存单元的值。因此 a 变为 20。
【易错点】 不熟悉指针的解引用(*p)赋值操作,或误以为 p 只是 a 的一个独立副本。
第 4 题(单选题)
以下哪种参数传递方式可以避免拷贝大型对象?
正确答案D
解析详情
【答案】D
【考点】参数传递方式
【解析】 值传递会创建对象的副本,消耗内存和时间。引用传递和指针传递都只是传递地址或别名,不涉及对象内容的拷贝,是处理大型对象的推荐方式。
【易错点】 误认为只有引用传递能避免拷贝,忽略了指针传递本质上也是传递地址。
第 5 题(单选题)
执行下述代码,将输出()。
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;
}正确答案D
解析详情
【答案】D
【考点】值传递与引用传递
【解析】 swap 函数中第一个参数 a 是值传递,x 的值(1)被拷贝给 a,对 a 的修改不影响 x。第二个参数 b 是引用传递,b 是 y 的别名,对 b 的修改即对 y 的修改。最终 x=1, y=1,输出 11。
【易错点】 忽略了第一个参数是值传递而非引用传递,从而误认为 x 会被修改。
第 6 题(单选题)
下面的描述中,()正确定义一个名为 Person 的结构体并正确初始化了一个 Person 结构体的变量 p 。
struct Person {
string name;
int age;
};
Person p("Yang", 10);struct Person {
string name,
int age;
};
Person p;
p.name = "Yang";
p.age = 10;struct Person {
string name;
int age;
};
Person p = { "Yang", 10 };struct Person {
string name;
int age;
};
Person p = new Person("Yang", 10);正确答案C
解析详情
【答案】C
【考点】结构体定义与初始化
【解析】 A 选项使用构造函数语法但未定义构造函数;B 选项定义中成员间使用了逗号;D 选项使用了错误的动态内存分配语法。C 选项是标准的列表初始化语法,正确。
【易错点】 不熟悉结构体的列表初始化 {} 语法,或混淆了 Java/C# 的 new 关键字用法。
第 7 题(单选题)
给定如下代码,
struct Person {
std::string name;
int age;
struct Address {
std::string street;
std::string city;
};
Address address;
};下面描述错误的是()。
正确答案D
解析详情
【答案】D
【考点】结构体嵌套
【解析】 结构体确实可以嵌套以逻辑化组织数据并减少命名冲突。但过深的嵌套会导致代码臃肿、访问路径过长且难以维护,必须根据实际需求控制嵌套层次。D 选项描述太绝对。
【易错点】 误认为编程规范中没有对嵌套层次的建议限制。
第 8 题(单选题)
假设 int arr[2][3] = {{1,2,3},{4,5,6}};,则 arr[1][2] 的值是()。
正确答案D
解析详情
【答案】D
【考点】二维数组索引
【解析】 C++ 数组索引从 0 开始。arr[1] 指向第二行 {4, 5, 6},arr[1][2] 指向该行的第三个元素,即 6。
【易错点】 错误地从 1 开始计数,将 arr[1] 认为第一行,或忽略了索引越界的风险。
第 9 题(单选题)
下面()正确定义了二维数组。
正确答案B
解析详情
【答案】B
【考点】二维数组定义语法
【解析】 C++ 二维数组的正确定义语法是 类型 数组名[行数][列数]。A、C、D 选项均不符合 C++ 语法要求。
【易错点】 受到 Python 或其他语言数组定义方式的影响,误选 A 或 C。
第 10 题(单选题)
小杨正在爬楼梯,需要爬 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;
}res += f1 + f2;
f1 = f2;
f2 = res;res = f1 + f2;
f1 = f2;
f2 = res;res += f1 + f2;
f2 = res;
f1 = f2;res = f1 + f2;
f2 = res;
f1 = f2;正确答案B
解析详情
【答案】B
【考点】递推算法(斐波那契数列)
【解析】 爬楼梯问题符合斐波那契数列递推关系 f(i) = f(i-1) + f(i-2)。在循环中,计算出当前项 res 后,需要将 f1 更新为原 f2,将 f2 更新为 res,为计算下一项做准备。
【易错点】 更新 f1 和 f2 的顺序写反,或在累加时错误使用了 += 导致重复计算。
第 11 题(单选题)
给定如下算法,其时间复杂度为()。
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;
}正确答案B
解析详情
【答案】B
【考点】时间复杂度分析
【解析】 外层循环执行 1 << n 即 2^n 次。内层循环固定执行 n 次。总的操作次数量级为 n * 2^n,因此时间复杂度为 O(n * 2^n)。
【易错点】 只注意到外层循环的 2^n 而忽略了内层循环的 n 次操作。
第 12 题(单选题)
下面关于排序稳定性的描述,正确的是()。
正确答案B
解析详情
【答案】B
【考点】排序算法稳定性
【解析】 稳定性是指如果两个元素值相等,排序后它们的相对先后顺序保持不变。选项 B 正确描述了这一概念。选择排序是不稳定的,插入排序是稳定的。
【易错点】 将“稳定性”误解为算法执行时间的稳定或结果的确定性。
第 13 题(单选题)
对数组 arr[]={5, 3, 8, 1} 进行升序排序,执行第一轮冒泡排序后数组 arr 中的内容为()。
正确答案A
解析详情
【答案】A
【考点】冒泡排序过程分析
【解析】 第一轮冒泡排序步骤:1. 比较 5,3 交换得 {3,5,8,1};2. 比较 5,8 不动;3. 比较 8,1 交换得 {3,5,1,8}。此时最大的 8 已被移动到最右侧。
【易错点】 忽略了中间步骤中的元素交换,或者将冒泡排序与选择排序混淆。
第 14 题(单选题)
运行下面的代码,将出现()。
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
解析详情
【答案】A
【考点】C++ 异常处理机制
【解析】 代码中 x=10, y=-10 满足 a == -b,hmean 抛出 runtime_error 异常。main 函数中的 try-catch 块捕获了该特定类型的异常并输出 Caught: ... 内容。
【易错点】 误以为异常未被捕获导致程序终止,或混淆了 catch 块的匹配优先级。
第 15 题(单选题)
下面哪种方式不能实现将字符串 "Happy Spring!" 输出重定向到文件 log.txt()。
cout << "Happy Spring!" << endl;
fclose(stdout);std::ofstream outFile("log.txt");
outFile << "Happy Spring!" << endl;
outFile.close();std::ofstream outFile("log.txt");
cout << "Happy Spring!" << endl;
outFile.close();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
【考点】文件重定向与输入输出流
【解析】 A 使用 freopen 重定向 stdout,B 直接向文件流输出,D 通过 rdbuf 修改 cout 绑定。C 选项虽然打开了文件流但未对 cout 做任何处理,cout 依然输出到标准设备。
【易错点】 误以为定义了一个名为 outFile 的文件流就能自动改变系统默认 cout 的行为。
判断题(每题 2 分)
第 1 题(判断题)
函数是C++中的核心概念,用于封装可重用的代码块。
正确答案正确
解析详情
【答案】正确
【考点】函数基本概念
【解析】 函数是 C++ 等结构化编程语言的核心组成部分,通过定义函数可以实现逻辑封装、降低复杂度并提高代码复用性。
【易错点】 无。
第 2 题(判断题)
在C++中,函数的返回类型可以省略,默认为 int。
正确答案错误
解析详情
【答案】错误
【考点】函数定义语法规范
【解析】 在现代 C++ 标准中,函数定义和声明必须明确指出返回类型。虽然早期的 C 语言可能支持默认 int,但 C++ 从未正式允许这种用法。
【易错点】 受到旧版 C 语言习惯或误解的影响。
第 3 题(判断题)
结构体的成员默认是 public 访问权限。
正确答案正确
解析详情
【答案】正确
【考点】结构体与类的访问权限区别
【解析】 在 C++ 中,struct 的成员默认访问权限是 public,而 class 的成员默认访问权限是 private。这是两者唯一的本质区别。
【易错点】 混淆 struct 和 class 的默认安全等级。
第 4 题(判断题)
假设整数数组 arr[4] = {0, 1, 2, 3}; 的第一个元素在内存中的地址为 0x7ffee4065820,经过 int* p = arr; p += 1;后,指针 p 的值是1。
正确答案错误
解析详情
【答案】错误
【考点】指针运算与内存地址
【解析】 执行 p += 1 后,指针 p 存储的地址值会增加一个 int 类型的偏移量(通常是 4 字节),而非变成数值 1。p 的值依然是一个内存地址。
【易错点】 混淆了指针本身存储的地址值与指针所指向的内容值。
第 5 题(判断题)
二维数组作为函数参数时,必须显式指定所有维度的大小。
正确答案错误
解析详情
【答案】错误
【考点】多维数组作为函数参数
【解析】 二维数组传参时,必须指定除第一维以外的所有维度的大小。第一维的大小可以省略,由编译器根据后续维度推导寻址逻辑。
【易错点】 记反了维度的省略规则,或者认为必须全写或全不写。
第 6 题(判断题)
递推是一种通过已知的初始值和递推公式,逐步求解目标值的算法。
正确答案正确
解析详情
【答案】正确
【考点】递推算法定义
【解析】 递推算法通过确定的状态转移方程,从初始状态(边界条件)出发迭代计算到目标状态,是解决动态规划等问题的常用手段。
【易错点】 无。
第 7 题(判断题)
考虑最坏情况下冒泡排序算法的时间复杂度,为待排序数字的数目为n的复杂度,则其递推关系式为,。
正确答案正确
解析详情
【答案】正确
【考点】冒泡排序算法复杂度分析
【解析】 冒泡排序最坏情况下,每轮需要完成 n 次比较操作来固定一个元素,因此 T(n) = T(n-1) + n。展开后即为等差数列求和,复杂度为 O(n^2)。
【易错点】 对算法复杂度用递推公式表达的形式感到陌生。
第 8 题(判断题)
插入排序在最好情况(已有序)下的时间复杂度是。
正确答案错误
解析详情
【答案】错误
【考点】插入排序算法复杂度
【解析】 插入排序在已有序的情况下,每轮只需进行 1 次比较且无需移动元素,总的时间复杂度降为 O(n)。
【易错点】 混淆了各种排序算法在最好、最坏和平均情况下的复杂度常识。
第 9 题(判断题)
对数组 arr[] = {4, 3, 1, 5, 2} 进行升序排序,执行第一轮选择排序后数组arr中的内容是 {1, 4, 3, 5, 2}。
正确答案错误
解析详情
【答案】错误
【考点】选择排序过程分析
【解析】 选择排序第一轮:在全序列中找到最小值 1,与首元素 4 交换。结果序列应为 {1, 3, 4, 5, 2}。题干中 3 和 4 的位置不对。
【易错点】 混淆了选择排序和冒泡排序的交换细节,或认为选择排序会顺便理顺中间序列。
第 10 题(判断题)
未捕获异常会调用std::terminate终止程序。
正确答案正确
解析详情
【答案】正确
【考点】C++ 异常处理生命周期
【解析】 如果程序中抛出的异常没有被任何匹配的 catch 块捕获,或者在处理异常的过程中又产生新异常,系统会调用 std::terminate() 立即终止程序运行。
【易错点】 误以为异常未处理时程序会处于未定义状态继续执行。