Appearance
C++相关题目
单选题
S01. 单选题
C++ 中多态的核心机制通常是?
A. 宏替换 B. 虚函数表和虚表指针 C. 命名空间 D. 预编译头
答案:B
解析:运行时多态常由 vptr/vtable 实现,基类指针或引用调用虚函数时根据动态类型分派。

S02. 单选题
通过基类指针 delete 派生类对象,基类析构函数应该?
A. 设为 virtual B. 设为 static C. 设为 inline 即可 D. 设为 private 一定正确
答案:A
解析:需要多态删除时,基类析构应为 virtual,否则派生资源可能不释放。

S03. 单选题
std::move 的作用是?
A. 立即搬移内存 B. 把对象转换成右值表达式 C. 删除对象 D. 复制对象
答案:B
解析:std::move 本身只是类型转换,真正移动发生在移动构造或移动赋值。

S04. 单选题
vector 扩容后一定失效的是?
A. 旧元素指针和迭代器 B. 所有 int 值 C. vector 类型本身 D. 编译器
答案:A
解析:扩容重新分配连续内存,旧存储上的指针、引用、迭代器失效。

S05. 单选题
map 和 unordered_map 的主要区别是?
A. map 有序,unordered_map 哈希无序 B. 二者都保证有序 C. map 只能存 int D. unordered_map 查询一定 O(log n)
答案:A
解析:map 常基于红黑树,按 key 有序;unordered_map 基于哈希表,平均 O(1),不保证顺序。

S06. 单选题
以下哪项最符合 RAII?
A. 资源生命周期绑定对象生命周期 B. 所有资源都用全局变量 C. 析构时永不释放 D. 只用于图形学
答案:A
解析:RAII 在构造获取资源、析构释放资源,是 C++ 异常安全的基础。

S07. 单选题
new/delete 与 malloc/free 的区别不包括?
A. new 会调用构造函数 B. delete 会调用析构函数 C. malloc 返回 void* D. malloc 会自动调用 C++ 构造函数
答案:D
解析:malloc 只分配原始内存,不调用构造函数。

S08. 单选题
const 成员函数中,普通成员变量默认?
A. 不能修改 B. 必须修改 C. 会自动变 static D. 只能在堆上修改
答案:A
解析:const 成员函数中的 this 指针是指向 const 对象的指针,普通成员不可改。

S09. 单选题
浅拷贝最容易导致的问题是?
A. 两个对象共享同一资源并重复释放 B. 代码变快 C. 无法编译任何程序 D. 变量名变短
答案:A
解析:含裸指针资源的类若默认浅拷贝,析构时可能双重释放。

S10. 单选题
C++ 中 static 局部变量的生命周期是?
A. 整个程序运行期间 B. 当前表达式 C. 当前 if 块 D. 只在编译期
答案:A
解析:static 局部变量具有静态存储期,只初始化一次,生命周期到程序结束。

S11. 单选题
函数重载主要依据什么区分?
A. 参数列表 B. 返回值类型 C. 注释 D. 文件名
答案:A
解析:C++ 函数重载看函数名和参数列表;仅返回值不同不能构成重载。

S12. 单选题
模板声明和实现通常为什么放头文件?
A. 编译实例化需要看到定义 B. 头文件运行更快 C. cpp 文件不能写模板 D. 模板不能有实现
答案:A
解析:模板在实例化时需要完整定义,常放头文件。

S13. 单选题
以下哪个容器插入/删除中间节点通常不会导致其他迭代器失效?
A. list B. vector C. deque 所有情况 D. string
答案:A
解析:list 节点独立分配,插入删除通常只影响被删除元素。

S14. 单选题
unordered_map rehash 后会发生什么?
A. 桶重建,迭代器可能失效 B. 自动排序 C. 所有 key 变成 0 D. 变成 vector
答案:A
解析:rehash 会重建桶数组并重新分布元素。

S15. 单选题
C++ 中引用必须?
A. 定义时初始化 B. 可以随时改绑定对象 C. 一定占 0 字节 D. 只能引用临时变量
答案:A
解析:引用是别名,必须初始化,之后不能重新绑定。

S16. 单选题
lambda 默认按值捕获时,外部变量在 lambda 内部默认?
A. 只读副本 B. 引用原对象 C. 会被删除 D. 变成 static
答案:A
解析:按值捕获复制变量;若要修改副本需 mutable,外部值不变。

S17. 单选题
atomic 主要解决什么问题?
A. 无锁原子读改写 B. 图形渲染 C. 压缩图片 D. 替代所有算法
答案:A
解析:atomic 用于原子操作和内存序控制,避免数据竞争。

S18. 单选题
mutex 的主要作用是?
A. 保护临界区 B. 提高显卡显存 C. 替代类继承 D. 自动优化 SQL
答案:A
解析:互斥锁保证同一时间只有一个线程进入临界区。

S19. 单选题
条件变量 condition_variable 通常配合什么使用?
A. mutex 和谓词条件 B. delete[] C. 纹理采样 D. 宏定义
答案:A
解析:条件变量等待条件变化,需要互斥锁保护共享状态,并用谓词避免虚假唤醒。

S33. 单选题
浮点数比较通常不建议直接 ==,原因是?
A. 浮点精度误差 B. float 无法存任何数 C. == 会删除对象 D. 编译器不支持
答案:A
解析:浮点运算存在舍入误差,通常比较差值是否小于 epsilon。

S34. 单选题
sizeof 空类对象通常至少为 1,是为了?
A. 保证不同对象有不同地址 B. 让对象无法创建 C. 节省所有内存 D. 禁用继承
答案:A
解析:C++ 要求不同对象可区分,空类对象大小通常为 1。

S35. 单选题
结构体内存对齐的主要目的?
A. 提升访问效率并满足平台约束 B. 让代码更短 C. 替代继承 D. 自动加密
答案:A
解析:对齐能让 CPU 更高效访问数据,也满足某些平台的硬件要求。

S36. 单选题
inline 与宏相比的优势包括?
A. 有类型检查和作用域规则 B. 一定不生成代码 C. 不能调试 D. 一定比宏慢
答案:A
解析:inline 是函数语义,保留类型检查;宏只是预处理文本替换。

S37. 单选题
虚继承主要解决?
A. 菱形继承中公共基类重复子对象问题 B. 网络重传 C. 贴图压缩 D. 哈希冲突
答案:A
解析:虚继承让菱形继承中共享同一份虚基类子对象。

S38. 单选题
placement new 的作用是?
A. 在已分配内存上构造对象 B. 自动申请网络连接 C. 释放数组 D. 排序 vector
答案:A
解析:placement new 不分配内存,只在指定地址调用构造函数。

S39. 单选题
dynamic_cast 常用于?
A. 多态类型安全向下转型 B. 整数加法 C. 宏展开 D. 文件写入
答案:A
解析:dynamic_cast 对多态类型进行运行时检查,失败返回 null 或抛异常。

不定项选择题
M01. 不定项选择题
关于 shared_ptr 正确的有?
A. 引用计数归零释放对象 B. 可能循环引用 C. 可配合 weak_ptr D. 一定比 unique_ptr 更适合所有场景
答案:A、B、C
解析:shared_ptr 表示共享所有权,不适合所有场景。

M02. 不定项选择题
哪些属于 STL 关联容器?
A. map B. set C. unordered_map D. vector
答案:A、B、C
解析:map/set 有序关联,unordered_map 是无序关联,vector 是序列容器。

M03. 不定项选择题
哪些会导致数据竞争风险?
A. 多个线程写同一变量且无同步 B. 一个线程读一个线程写且无同步 C. 只读共享常量 D. 使用 mutex 保护
答案:A、B
解析:无同步读写共享可变数据会有数据竞争。

M04. 不定项选择题
关于右值引用正确的有?
A. 可用于移动语义 B. 形如 T&& C. 命名右值引用变量本身是左值 D. 只能绑定 int
答案:A、B、C
解析:命名变量都是左值,即使类型是 T&&。

M05. 不定项选择题
下列哪些是常见未定义行为?
A. 数组越界 B. 解引用空指针 C. 有符号整数溢出 D. vector.size()
答案:A、B、C
解析:这些都可能造成未定义行为,笔试读代码题常考。

M08. 不定项选择题
常见线程同步方式包括?
A. mutex B. condition_variable C. atomic D. reinterpret_cast
答案:A、B、C
解析:类型转换不是同步机制。

M09. 不定项选择题
可能造成内存泄漏的有?
A. new 后路径提前 return 未 delete B. shared_ptr 循环引用 C. 容器自动析构 D. 异常跳过手动释放
答案:A、B、D
解析:RAII/智能指针能缓解手动释放路径遗漏。

M10. 不定项选择题
关于多态正确的有?
A. 虚函数支持动态绑定 B. 纯虚函数可使类成为抽象类 C. 构造函数内虚调用不会分派到派生类 D. 静态函数可以是 virtual
答案:A、B、C
解析:static 成员函数没有 this,不能是虚函数。

M19. 不定项选择题
关于 const 正确的有?
A. 可修饰变量 B. 可修饰成员函数 C. 可参与函数重载 D. 等同于宏
答案:A、B、C
解析:const 有类型和作用域,宏只是文本替换。

M20. 不定项选择题
关于内存对齐正确的有?
A. 可能产生 padding B. 影响 sizeof C. 提升访问效率 D. static 成员一定算入对象大小
答案:A、B、C
解析:static 成员属于类,不计入单个对象大小。

M24. 不定项选择题
哪些可能是代码输出题陷阱?
A. 未定义行为 B. 构造析构顺序 C. 重载决议 D. 注释字数
答案:A、B、C
解析:读代码输出常考 C++ 语义边界。

M25. 不定项选择题
关于 cache 友好正确的有?
A. 连续内存通常局部性更好 B. 频繁随机访问可能 miss 多 C. 结构体布局会影响缓存 D. cache 与性能无关
答案:A、B、C
解析:游戏性能优化常关注缓存局部性。

代码填空
F04. 代码填空
补全单例。
cpp
class S {
public:
static S& ins() {
static /*1*/ obj;
return obj;
}
private:
S()=default;
S(const S&)=/*2*/;
S& operator=(const S&)=/*3*/;
};答案:
cpp
S
delete
delete解析:局部静态对象懒加载,删除拷贝避免多个实例。

F05. 代码填空
补全 RAII 锁。
cpp
class Guard {
mutex& m;
public:
Guard(mutex& x):m(x) {
/*1*/
}
~Guard() {
/*2*/
}
};答案:
cpp
m.lock();
m.unlock();解析:构造加锁,析构解锁,保证异常路径释放。

F07. 代码填空
补全 unique_ptr 移交。
cpp
unique_ptr<int> a(new int(3));
unique_ptr<int> b = /*1*/;答案:
cpp
std::move(a)解析:unique_ptr 独占所有权,不可拷贝,只能移动。

F11. 代码填空
补全 vector 删除遍历写法。
cpp
for (auto it=v.begin(); it!=v.end(); ) {
if (*it%2==0) {
it=/*1*/;
}
else {
/*2*/;
}
}答案:
cpp
v.erase(it)
++it解析:erase 返回删除后下一个有效迭代器。

F12. 代码填空
补全移动构造清空源对象。
cpp
Buffer(Buffer&& o):p(o.p), n(o.n) {
o.p=/*1*/;
o.n=/*2*/;
}答案:
cpp
nullptr
0解析:接管资源后清空源对象,避免双重释放。

F15. 代码填空
补全析构释放数组。
cpp
~Array() {
delete /*1*/ data;
}答案:
cpp
[]解析:new[] 分配的数组必须用 delete[] 释放。

读代码输出
O01. 读代码输出
构造析构顺序。
cpp
#include <iostream>
using namespace std;
struct A {
A() {
cout<<"A";
}
~A() {
cout<<"a";
}
};
struct B {
B() {
cout<<"B";
}
~B() {
cout<<"b";
}
};
int main() {
A x;
B y;
cout<<"M";
}输出:
text
ABMba解析:局部对象按构造逆序析构。

O02. 读代码输出
虚函数构造期调用。
cpp
#include <iostream>
using namespace std;
struct B {
B() {
f();
}
virtual void f() {
cout<<"B";
}
};
struct D:B {
void f() override {
cout<<"D";
}
};
int main() {
D d;
}输出:
text
B解析:基类构造期间虚调用不会分派到派生类。

O03. 读代码输出
引用别名。
cpp
#include <iostream>
using namespace std;
int main() {
int x=1;
int& r=x;
r=9;
cout<<x;
}输出:
text
9解析:引用是别名,修改 r 就是修改 x。

O04. 读代码输出
map operator[]。
cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
map<string, int> m;
cout<<m["hp"]<<" "<<m.size();
}输出:
text
0 1解析:operator[] 访问不存在 key 会插入默认值。

O05. 读代码输出
lambda 值捕获。
cpp
#include <iostream>
using namespace std;
int main() {
int x=10;
auto f=[x]() mutable {
x+=2;
return x;
};
cout<<f()<<" "<<x;
}输出:
text
12 10解析:mutable 修改的是捕获副本。

O06. 读代码输出
sizeof 数组。
cpp
#include <iostream>
using namespace std;
int main() {
int a[4]= {
};
cout<<sizeof(a)/sizeof(a[0]);
}输出:
text
4解析:数组当前作用域未退化,sizeof 得到总字节数。

O07. 读代码输出
重载决议。
cpp
#include <iostream>
using namespace std;
void f(int) {
cout<<"i";
}
void f(double) {
cout<<"d";
}
int main() {
f(1.0f);
}输出:
text
d解析:float 到 double 是提升,优于转 int。

O08. 读代码输出
vector 迭代器陷阱。
cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
vector<int> v= {
1, 2, 3
};
auto it=v.begin();
v.push_back(4);
cout<<*it;
}输出:
text
未定义行为解析:push_back 可能扩容导致 it 失效。

O09. 读代码输出
static 局部变量。
cpp
#include <iostream>
using namespace std;
void f() {
static int x=0;
cout<<++x;
}
int main() {
f();
f();
f();
}输出:
text
123解析:static 局部变量只初始化一次,值跨调用保留。

O10. 读代码输出
前置后置自增。
cpp
#include <iostream>
using namespace std;
int main() {
int x=1;
cout<<x++<<" "<<++x;
}输出:
text
1 3解析:后置先返回旧值再加,前置先加再返回。

O11. 读代码输出
多态删除缺虚析构。
cpp
#include <iostream>
using namespace std;
struct B {
~B() {
cout<<"B";
}
};
struct D:B {
~D() {
cout<<"D";
}
};
int main() {
B* p=new D;
delete p;
}输出:
text
未定义行为/常见只输出B解析:通过无虚析构的基类指针删除派生对象是未定义行为,不能把常见输出当标准答案。

O12. 读代码输出
字符串长度。
cpp
#include <iostream>
#include <cstring>
using namespace std;
int main() {
char s[]="abc";
cout<<sizeof(s)<<" "<<strlen(s);
}输出:
text
4 3解析:字符数组含结尾 \0,strlen 不计 \0。

O13. 读代码输出
指针算术。
cpp
#include <iostream>
using namespace std;
int main() {
int a[]= {
10, 20, 30
};
int* p=a;
cout<<*(p+2);
}输出:
text
30解析:p+2 指向第三个元素。

O14. 读代码输出
函数默认参数。
cpp
#include <iostream>
using namespace std;
void f(int a, int b=2) {
cout<<a+b;
}
int main() {
f(3);
}输出:
text
5解析:未传 b 时使用默认参数 2。

O15. 读代码输出
短路求值。
cpp
#include <iostream>
using namespace std;
int main() {
int x=0;
if (x && ++x) {
}
cout<<x;
}输出:
text
0解析:&& 左侧为 false 时右侧不执行。

O16. 读代码输出
shared_ptr 引用计数。
cpp
#include <iostream>
#include <memory>
using namespace std;
int main() {
auto p=make_shared<int>(1);
auto q=p;
cout<<p.use_count();
}输出:
text
2解析:p 和 q 共享同一对象,引用计数为 2。

O17. 读代码输出
虚函数动态绑定。
cpp
#include <iostream>
using namespace std;
struct B {
virtual void f() {
cout<<"B";
}
};
struct D:B {
void f() override {
cout<<"D";
}
};
int main() {
D d;
B& b=d;
b.f();
}输出:
text
D解析:通过基类引用调用虚函数,动态绑定到 D::f。

O18. 读代码输出
优先级。
cpp
#include <iostream>
using namespace std;
int main() {
cout<<(1+2*3);
}输出:
text
7解析:乘法优先于加法。

O19. 读代码输出
deque 简单操作。
cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
deque<int> q;
q.push_back(1);
q.push_front(2);
cout<<q.front()<<q.back();
}输出:
text
21解析:push_front 放前面,push_back 放后面。

O20. 读代码输出
set 去重排序。
cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
set<int> s= {
3, 1, 3, 2
};
for (int x:s) {
cout<<x;
}
}输出:
text
123解析:set 去重并按 key 有序遍历。
