#include
#include
#include
// 测试vector的reserve对性能的影响
void test_vector_reserve() {
const int N = 1000000;
// 不预分配内存
{
std::vector<int> v;
auto start = std::chrono::high_resolution_clock::now();
for(int i=0; i<N; ++i) {
v.push_back(i);
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Without reserve: "
<< std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()
<< "μs\n";
}
// 预分配内存
{
std::vector<int> v;
v.reserve(N);
auto start = std::chrono::high_resolution_clock::now();
for(int i=0; i<N; ++i) {
v.push_back(i);
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "With reserve: "
<< std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()
<< "μs\n";
}
}
int main() {
test_vector_reserve();
return 0;
}
输出示例:
Without reserve: 5432μs
With reserve: 1276μs
关键点:
reserve()
预分配内存避免多次重新分配#include
#include
#include
// 原始单元素处理接口
void process_element(std::vector<int>& vec, int value) {
vec.push_back(value * 2);
}
// 优化的批量处理接口
void process_batch(std::vector<int>& vec, const std::vector<int>& values) {
vec.reserve(vec.size() + values.size());
for(auto v : values) {
vec.push_back(v * 2);
}
}
void test_batch_processing() {
const int N = 10000;
std::vector<int> input(N, 5);
// 单次处理测试
{
std::vector<int> result;
auto start = std::chrono::high_resolution_clock::now();
for(auto v : input) {
process_element(result, v);
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Single processing: "
<< std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()
<< "μs\n";
}
// 批量处理测试
{
std::vector<int> result;
auto start = std::chrono::high_resolution_clock::now();
process_batch(result, input);
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Batch processing: "
<< std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()
<< "μs\n";
}
}
int main() {
test_batch_processing();
return 0;
}
输出示例:
Single processing: 856μs
Batch processing: 213μs
关键点:
#include
#include
// 深层次调用链
class DeepCallChain {
public:
void level3(int x) { data = x * 2; }
void level2(int x) { level3(x); }
void level1(int x) { level2(x); }
int get() const { return data; }
private:
int data;
};
// 扁平化调用链
class FlatCallChain {
public:
void process(int x) { data = x * 2; }
int get() const { return data; }
private:
int data;
};
void test_call_chain() {
const int N = 1000000;
// 深层次调用
{
DeepCallChain obj;
auto start = std::chrono::high_resolution_clock::now();
for(int i=0; i<N; ++i) {
obj.level1(i);
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Deep call chain: "
<< std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()
<< "μs\n";
}
// 扁平调用
{
FlatCallChain obj;
auto start = std::chrono::high_resolution_clock::now();
for(int i=0; i<N; ++i) {
obj.process(i);
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Flat call chain: "
<< std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()
<< "μs\n";
}
}
int main() {
test_call_chain();
return 0;
}
输出示例:
Deep call chain: 2563μs
Flat call chain: 1245μs
关键点:
#include
#include
#include
#include
void test_access_method() {
const int N = 100000;
std::vector<int> data(N);
std::iota(data.begin(), data.end(), 0);
// 查找方式访问
{
int sum = 0;
auto start = std::chrono::high_resolution_clock::now();
for(int i=0; i<N; ++i) {
auto it = std::find(data.begin(), data.end(), i);
if(it != data.end()) sum += *it;
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Find access: "
<< std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()
<< "μs\n";
}
// 直接索引访问
{
int sum = 0;
auto start = std::chrono::high_resolution_clock::now();
for(int i=0; i<N; ++i) {
sum += data[i];
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << "Direct access: "
<< std::chrono::duration_cast<std::chrono::microseconds>(end-start).count()
<< "μs\n";
}
}
int main() {
test_access_method();
return 0;
}
输出示例:
Find access: 12563μs
Direct access: 256μs
关键点:
g++ -std=c++11 -O2 example.cpp -o example
./example
关于标准库容器的性能优化,以下哪些说法正确?
A) vector的push_back时间复杂度是O(n)
B) unordered_map的查找复杂度总是O(1)
C) deque在中间插入元素的时间复杂度是O(n)
D) list的迭代器失效规则与vector相同
下列哪些方法可以有效减少动态内存分配?
A) 使用对象池模式
B) 优先使用emplace_back代替push_back
C) 为string预先调用reserve()
D) 使用std::make_shared创建智能指针
关于字符串优化,哪些做法正确?
A) 小字符串优化(SSO)可以避免堆分配
B) 使用+=拼接比多次operator+更高效
C) 移动语义可以完全消除字符串拷贝
D) c_str()调用会触发深拷贝
以下哪些算法选择可能提升性能?
A) 用std::sort替代冒泡排序
B) 用std::lower_bound替代线性查找
C) 用std::list替代std::vector存储频繁修改的序列
D) 用std::array替代原始数组
关于内存分配器,正确的有:
A) 自定义分配器可以减少锁竞争
B) std::allocator是线程安全的
C) 内存池适合固定大小对象的分配
D) 对齐分配对SIMD指令很重要
哪些模板使用可能影响性能?
A) 深度嵌套的模板实例化
B) 递归模板元编程
C) 使用类型擦除的any类型
D) 模板参数推导失败
关于异常处理,正确的有:
A) 异常规范影响代码优化
B) try块会增加函数调用开销
C) noexcept声明帮助编译器优化
D) 异常捕获应尽量精确
缓存友好的设计包括:
A) 使用紧凑数据结构
B) 预取相邻内存数据
C) 随机访问链表节点
D) 对齐内存访问边界
编译器优化相关:
A) -O3可能增加代码体积
B) LTO优化链接时代码
C) PGO需要训练数据
D) restrict关键字帮助别名分析
线程安全优化策略:
A) 读写锁减少竞争
B) thread_local变量避免锁
C) 无锁数据结构消除等待
D) 原子操作总是比锁高效
设计题1:高效字符串拼接
// 要求:实现零拷贝的字符串拼接,支持链式调用
class StringBuilder {
public:
StringBuilder& append(const std::string& s);
std::string build();
private:
// 设计存储结构
};
设计题2:内存池分配器
// 实现固定块大小的内存池,支持STL容器
template <typename T>
class PoolAllocator {
public:
using value_type = T;
// 必要接口实现
};
设计题3:类型擦除优化
// 设计替代虚函数调用的高效多态方案
template <typename T>
class FunctionWrapper {
public:
template <typename F>
FunctionWrapper(F&& f);
void operator()() const;
private:
// 存储策略
};
设计题4:SIMD优化矩阵乘法
// 使用AVX指令优化4x4矩阵乘法
void matrix_multiply_avx(const float* a, const float* b, float* result);
设计题5:无锁队列
// 实现多生产者单消费者的无锁队列
template <typename T>
class LockFreeQueue {
public:
void push(const T& value);
bool pop(T& value);
private:
// 设计节点结构和原子操作
};
BC
C正确,deque中间插入O(n);B哈希表平均O(1)
A错,摊销O(1);D错,vector插入会使迭代器失效
ABCD
全部正确,B/D减少临时对象,A/C预分配
AB
C错,移动可能保留容量;D错,c_str()不触发拷贝
AB
C错,vector更适合随机访问;D类型安全但性能相同
ACD
B错,标准分配器线程安全但可能有锁
ABC
D是编译错误,不影响运行性能
ACD
B错,try块本身无运行时开销
ABD
C链表导致缓存不命中
ABCD
全部正确
ABC
D错,原子操作可能更慢
设计题1实现:
class StringBuilder {
std::vector<std::reference_wrapper<const std::string>> parts;
public:
StringBuilder& append(const std::string& s) {
parts.emplace_back(s);
return *this;
}
std::string build() const {
size_t total = 0;
for (const auto& s : parts) total += s.get().size();
std::string result;
result.reserve(total);
for (const auto& s : parts) result += s.get();
return result;
}
};
// 测试用例
int main() {
StringBuilder sb;
sb.append("Hello").append(" ").append("World");
assert(sb.build() == "Hello World");
}
设计题2实现:
template <typename T>
class PoolAllocator {
struct Block { Block* next; };
Block* freeList = nullptr;
public:
T* allocate(size_t n) {
if (n != 1 || !freeList) {
return static_cast<T*>(::operator new(n * sizeof(T)));
}
auto head = freeList;
freeList = freeList->next;
return reinterpret_cast<T*>(head);
}
void deallocate(T* p, size_t n) {
if (n != 1) {
::operator delete(p);
return;
}
auto block = reinterpret_cast<Block*>(p);
block->next = freeList;
freeList = block;
}
};
剩下的设计题目, 后续补充