← 练习册目录

第 3 章 函数与引用

red wenzi · 2026-09-15 · 编程语言 · C++ · 练习册 · 15 题
📝 本章练习:15 题(A 识别 / B 理解 / C 改错 / D 写程序)。先自己做完再看答案——A、B 档不翻书做,C、D 档必须真的编译运行。

3.1 函数与重载

A1识别判断题:两个函数只靠返回类型不同(一个 int f(),一个 double f())可以构成重载。

答:______________

✅ 查看答案与解析

答案 错

解析:返回类型不能区分重载,会直接报错。重载靠参数列表(个数或类型)不同来区分。

A2识别判断题:默认参数只能写在声明里,而且必须从右往左连续。

答:______________

✅ 查看答案与解析

答案 对

解析:int f(int a, int b = 10); 合法;int f(int a = 1, int b); 不合法,因为跳过了左边的默认值。

B1理解选择题:int f(int a = 1, int b); 这个声明合法吗?

合法

不合法,默认参数必须从右往左连续

不合法,函数不能有默认参数

合法但运行时出错

答:______________

✅ 查看答案与解析

答案 B

解析:默认参数必须从右往左连续填写,中间不能断。

C1应用改错题:下面函数有的路径没有返回值,是未定义行为。
int findValue(int x) {
    if (x > 0) { return 1; }
    // x <= 0 时走到这里,没有 return
}
✅ 查看答案与解析

答案 给所有路径补返回值,例如:

解析:函数必须保证所有路径都有返回值,否则是未定义行为。

int findValue(int x) {
    if (x > 0) { return 1; }
    return 0;
}
D1创造写程序:写一个函数 maxOf(int a, int b),main 里读两个数调用它输出较大值。

提示:用条件运算符 a > b ? a : b。

✅ 查看答案与解析

答案 参考答案:

解析:先声明后使用;函数定义放在调用之前即可。

#include <iostream>
int maxOf(int a, int b) { return a > b ? a : b; }
int main() {
    int a, b;
    std::cin >> a >> b;
    std::cout << maxOf(a, b) << '\n';
    return 0;
}

3.2 值、引用、指针传递

A1识别判断题:引用必须初始化,一旦绑定就不能改绑。

答:______________

✅ 查看答案与解析

答案 对

解析:int& r; 编译不过;r = b; 是把 b 的值赋给 a,不是让 r 改指 b。引用只是别名,没有自己的身份。

B1理解选择题:执行下面代码后,a 的值是多少?

1

100

0

编译错误

答:______________

✅ 查看答案与解析

答案 B

解析:void byRef(int& x) { x = 100; } 传引用,改的就是原变量 a,所以 a 变成 100。

B2理解选择题:函数返回局部变量的引用,会发生什么?

正常返回

返回一个拷贝

得到悬垂引用,使用它是未定义行为

编译一定报错

答:______________

✅ 查看答案与解析

答案 C

解析:局部变量在函数返回时销毁,返回它的引用得到悬垂引用。编译器通常给 -Wreturn-local-addr 警告。

C1应用改错题:下面函数想返回局部变量的引用,请改安全。
int& bad() {
    int x = 42;
    return x;    // x 离开函数就销毁了
}
✅ 查看答案与解析

答案 改成返回值:int bad() { int x = 42; return x; }

解析:按值返回局部对象通常零拷贝,不需要为了“性能”返回引用。

(编译器会做返回值优化 RVO,不拷贝。)
D1创造写程序:写一个引用版 swap(int& a, int& b),交换两个变量的值,并在 main 中验证。

提示:void swap(int& x, int& y) { int t = x; x = y; y = t; }

✅ 查看答案与解析

答案 参考答案:

解析:引用版 swap 改的就是原变量;如果用值传递,交换只发生在副本上。

#include <iostream>
void swap(int& a, int& b) {
    int t = a; a = b; b = t;
}
int main() {
    int x = 3, y = 5;
    swap(x, y);
    std::cout << x << ' ' << y << '\n';   // 5 3
    return 0;
}

3.3 多文件与命名空间

A1识别判断题:#pragma once 用来防止同一个头文件被重复包含。

答:______________

✅ 查看答案与解析

答案 对

解析:头文件保护,防止重复包含导致重复定义。

A2识别判断题:using namespace std; 不要写在头文件里。

答:______________

✅ 查看答案与解析

答案 对

解析:头文件会被复制到很多源文件,等于强迫所有包含它的人都接受 std 的全部名字,容易冲突。

B1理解选择题:下面哪句话正确?

编译期看定义,链接期看声明

编译期看声明,链接期看定义

编译和链接都只看声明

编译和链接都只看定义

答:______________

✅ 查看答案与解析

答案 B

解析:头文件放声明(“有这么个东西”),源文件放定义(“它长这样”)。编译各文件时只需声明,链接时才核对定义。

C1应用改错题:两个源文件都定义了一个全局函数 foo,链接时报 duplicate symbol。
a.cpp(单独保存为一个文件)
void foo() { }
b.cpp(单独保存为一个文件)
void foo() { }
✅ 查看答案与解析

答案 同一个名字在整个程序里只能有一个定义(ODR)。把其中一个改名,或把公共实现放进头文件用 inline 修饰。

解析:inline 函数的定义可以在多个编译单元里重复出现,链接器合并成一个——这是 inline 今天最主要的用途。

D1创造写程序:把一个求平方的小函数拆成 util.h(声明)+ util.cpp(定义)+ main.cpp(调用),用一条 g++ 命令编译运行。

提示:g++ -std=c++17 -Wall -Wextra -o app main.cpp util.cpp

✅ 查看答案与解析

答案 参考答案:

解析:头文件加 #pragma once;普通函数声明放头文件、定义放 .cpp;main 只 #include "util.h"。

// util.h
#pragma once
double square(double x);
// util.cpp
#include "util.h"
double square(double x) { return x * x; }
// main.cpp
#include "util.h"
#include <iostream>
int main() {
    std::cout << square(3.0) << '\n';   // 9
    return 0;
}
📚 相关概念:编译与链接 · STL · map / set · 迭代器