腾讯wxg客户端一面 面经 (好像也没有那么难)
1. 先做个自我介绍吧
您好,我是[姓名],目前就读于[学校][专业]。我主要的技术方向是C++客户端开发,熟悉C++11/14/17新特性、STL容器和算法,有Qt框架的项目经验。
在校期间参与过[项目名称],主要负责[具体模块]的开发,使用了Qt进行界面开发和信号槽机制实现模块间通信。最近在[公司]实习,参与了[项目]的开发,积累了一些实际项目经验。
我对客户端开发很感兴趣,平时会关注性能优化、内存管理等方面的技术,也在LeetCode上刷题保持算法能力。很期待能加入腾讯WXG团队,参与微信这样亿级用户产品的开发。
2. C++11/14/17有哪些新特性是你常用的?
我常用的新特性包括:
智能指针(shared_ptr、unique_ptr、weak_ptr):自动管理内存,避免内存泄漏,替代了传统的裸指针和手动delete。
右值引用和移动语义:通过std::move减少不必要的拷贝,提升性能,特别是在容器操作和函数返回时。
Lambda表达式:简化回调函数的编写,配合STL算法使用很方便。
auto关键字:自动类型推导,简化代码,特别是迭代器声明时。
范围for循环:遍历容器更简洁。
std::thread和并发库:原生支持多线程编程。
constexpr:编译期计算,提升运行时性能。
结构化绑定(C++17):方便地解构tuple和pair。
std::optional(C++17):优雅地处理可能不存在的值。
这些特性让C++代码更现代化、更安全、性能也更好。
3. STL中你用过哪些容器和算法?
容器方面:
- 序列容器:vector(最常用)、deque、list,根据场景选择
- 关联容器:map、set、unordered_map、unordered_set,需要排序用前者,追求查找性能用后者
- 适配器:stack、queue、priority_queue
算法方面:
- 排序:sort、stable_sort、partial_sort
- 查找:find、binary_search、lower_bound、upper_bound
- 遍历:for_each、transform
- 数值:accumulate
- 其他:remove_if、unique、reverse等
实际项目中,我会根据时间复杂度和空间复杂度选择合适的容器。比如需要频繁随机访问用vector,需要频繁插入删除用list,需要快速查找用unordered_map。
4. Lambda表达式和仿函数有什么区别?各自的优势是什么?
Lambda表达式是C++11引入的匿名函数,语法简洁,可以捕获外部变量。仿函数是重载了operator()的类对象。
主要区别:
语法:Lambda更简洁,适合简单逻辑;仿函数需要定义类,代码量大但结构清晰。
状态管理:仿函数可以有成员变量,状态管理更灵活;Lambda通过捕获列表获取外部变量。
复用性:仿函数可以在多处使用,有明确的类型;Lambda通常是一次性使用,类型由编译器推导。
性能:两者性能相近,都可以被内联优化。
使用场景:简单的回调、STL算法的谓词用Lambda;复杂逻辑、需要复用、需要多个成员函数的场景用仿函数。
例如:
// Lambda
std::sort(vec.begin(), vec.end(), [](int a, int b) { return a > b; });
// 仿函数
struct Greater {
bool operator()(int a, int b) const { return a > b; }
};
std::sort(vec.begin(), vec.end(), Greater());
5. 为什么说shared_ptr在某些场景下性能优于unique_ptr?
这个说法需要具体场景分析,通常情况下unique_ptr性能更好,因为它没有引用计数的开销。但在某些场景下shared_ptr确实有优势:
多线程共享:当多个线程需要共享同一对象时,shared_ptr的引用计数是线程安全的(原子操作),而unique_ptr无法直接共享,需要额外的同步机制。
避免深拷贝:传递大对象时,shared_ptr只需拷贝指针和增加引用计数,而如果用unique_ptr需要转移所有权或者拷贝整个对象。
缓存场景:多个地方需要持有同一对象的引用,shared_ptr自动管理生命周期,最后一个引用释放时才析构。
不过需要注意,shared_ptr的引用计数操作(即使是原子的)仍有开销,而且可能导致循环引用问题。如果确定只有单一所有权,unique_ptr是更好的选择。
6. make_shared和直接用new构造shared_ptr有什么区别?
主要区别在于内存分配和性能:
内存分配次数:
make_shared<T>(args):一次内存分配,同时分配对象和控制块shared_ptr<T>(new T(args)):两次内存分配,先分配对象,再分配控制块
性能:make_shared更快,内存局部性更好,减少了内存碎片。
异常安全:make_shared更安全。考虑func(shared_ptr<T>(new T()), other_func()),如果other_func抛异常,new T()可能泄漏;make_shared不会有这个问题。
控制块释放:make_shared的对象和控制块在同一内存块,只有当weak_ptr也释放时才能完全释放内存;直接new构造的可以分别释放。
自定义删除器:make_shared不支持自定义删除器,需要用shared_ptr构造函数。
推荐优先使用make_shared,除非需要自定义删除器或者有特殊的内存管理需求。
7. unique_ptr在线程池中传参会遇到什么问题?怎么解决?
主要问题是unique_ptr不能拷贝,只能移动,而很多线程池接口接受的是可拷贝的函数对象。
问题场景:
std::unique_ptr<Data> data =
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
本专栏系统梳理C++技术面试核心考点,涵盖语言基础、面向对象、内存管理、STL容器、模板编程及经典算法。从引用指针、虚函数表、智能指针等底层原理,到继承多态、运算符重载等OOP特性从const、static、inline等关键字辨析,到动态规划、KMP算法、并查集等手写实现。每个知识点以面试答题形式呈现,注重原理阐述而非冗长代码,帮助你快速构建完整知识体系,从容应对面试官提问,顺利拿下offer。

查看19道真题和解析