腾讯研发笔试核心考点拆解:从C++内存布局到算法基础
2026/8/30 16:08:21 网站建设 项目流程

这套题放在今天来看,考点依然非常“经典”:C++对象内存布局、排序算法稳定性、进程线程区别、TCP握手状态、链表操作、动态规划……几乎每个大厂笔试都会换着花样考。但腾讯这套题有个特点,它不追求偏题怪题,而是把所有研发工程师“应该会”的基础能力浓缩到一张卷子里,区分度很高。我刷完第一遍的时候对答案对到怀疑人生,很多题看着眼熟,一选就错。今天我把这套题涉及的核心考点、解题思路、容易踩的坑,以及我从面试官视角反推出来的备考策略,一次性拆开聊清楚。

1. 这套题到底在考什么:题型分布与考察逻辑

1.1 整体结构回顾

腾讯2016研发工程师笔试题(一),从题型上看,以选择题为主,偶尔会有简答或编程题,整体分为几大块:C/C++语言基础、数据结构与算法、操作系统、计算机网络,以及少量智力题或逻辑题。很多人拿到卷子第一反应是“怎么都是选择题”,但真正做起来才发现,选择题往往比编程题更容易暴露知识盲区,因为选项里全是精心设计的陷阱。

从题目分布来看,C/C++语言基础占了将近三分之一,重点集中在指针、内存管理、构造函数/析构函数、虚函数表、const/static关键字、运算符优先级这些点上。数据结构与算法同样是大头,链表反转、二叉树遍历、排序算法比较、哈希冲突处理、动态规划都是高频考点。操作系统部分主要考进程与线程、死锁条件、内存分页、虚拟内存。计算机网络则集中在TCP/UDP、三次握手四次挥手、HTTP状态码、DNS解析过程。

这套题给我的第一感觉是:覆盖面很广,但深度并不夸张。它不像某些竞赛题那样需要奇技淫巧,更多是在考察你有没有把计算机基础学扎实。你如果平时写业务代码写得顺手,但基础概念模糊,这套题能直接把你打回原形。

1.2 为什么这些知识点被反复拿出来考

我后来跟做校招的同事聊过,他说腾讯技术岗笔试的出题逻辑其实很明确:基础知识决定你能走多快,底层原理决定你能走多远。笔试不指望你写出多惊艳的算法,而是想确认三件事:

  • 你有没有完整的计算机知识体系,而不是只会调接口、写CRUD;
  • 你在写代码的时候,是不是真的理解内存里发生了什么、网络请求经过哪些节点;
  • 你在遇到复杂问题的时候,能不能快速定位到合适的数据结构和算法模型。

这也是为什么C++在腾讯笔试里占比这么高。虽然现在很多业务用Go、Java,但C++能考察到的东西太丰富了:指针让你理解内存本质,虚函数让你理解运行时多态,内存管理让你理解栈和堆的区别。把这些基础打牢,换任何语言都能很快上手。

还有一个容易被忽略的点:这些题目也在间接考察你的取舍能力。排序算法考稳定性、哈希考冲突解决、进程线程考并发模型,本质上都是让你在多个方案之间做选择。笔试题目把选择空间压缩到选项里,但背后考察的决策逻辑,和实际工作中的技术选型是相通的。

2. 核心知识点拆解:那些容易被忽略的细节

2.1 C/C++语言基础:指针、内存与关键字

这套题里关于C/C++的部分,给我留下最深印象的是几道围绕指针和内存展开的题。比如 sizeof 和 strlen 的区别、指针数组和数组指针的区别、二维数组作为函数参数时的退化问题。很多非科班出身的同学会在这些地方丢分,因为平时写代码很少直接操纵内存地址。

举个例子,面试题里经常出现类似这样的代码:

char *p = "hello"; char arr[] = "hello"; printf("%d %d\n", sizeof(p), sizeof(arr));

这里 sizeof(p) 在64位系统下结果是8(指针大小),而 sizeof(arr) 结果是6(包含结尾的'\0')。但如果你不熟悉指针和数组的本质区别,很容易被这个结果绕晕。指针保存的是地址,数组是一段连续内存的名字,这两个概念在笔试里被翻来覆去地考。

还有一个高频考点是虚函数和虚函数表。腾讯特别喜欢考“含有虚函数的类,其对象内存布局是什么样”这类题。理解的关键在于:

  • 类中只要有虚函数,对象头就会有一个虚函数表指针(vptr),指向该类维护的一张虚函数表(vtable);
  • 虚函数表里按声明顺序存放每个虚函数的地址;
  • 继承时,派生类会覆盖虚函数表中对应项的地址。

笔试常考“sizeof(类)”的大小计算题。比如一个类只有两个int成员和一个虚函数,在64位机器上sizeof结果往往是16,而不是12,因为内存对齐会让int占8字节,再叠加vptr的8字节。这种题看似是计算,实际考的是你对对象内存模型的理解。我建议刷题时遇到这类题,一定要画内存布局图,把成员变量、vptr、对齐字节都标出来,思路立刻清晰。

2.2 数据结构与算法:从链表到动态规划

数据结构部分,腾讯这套题明显偏爱链表和二叉树。链表反转出现过不止一次,而且经常变着花样出:反转整个链表、反转区间内的节点、判断链表是否有环。核心思路就是指针操作,但考场上容易因为边界条件写错。

我复习时候整理了一个通用模板,以反转单链表为例:

struct ListNode { int val; ListNode* next; }; ListNode* reverseList(ListNode* head) { ListNode* prev = nullptr; ListNode* cur = head; while (cur) { ListNode* next = cur->next; cur->next = prev; prev = cur; cur = next; } return prev; }

这个模板的关键就是记住三句话:先保存下一个节点,再改当前节点的 next 指向前一个,最后整体后移。看起来简单,但很多人在手写代码时会忘了第一步,导致链表断掉。笔试不一定会要求你直接写代码,但选择题里会考“执行某次操作后,节点指针指向哪里”这一类问题,本质上还是考你有没有真正理解指针变化的每一步。

二叉树部分,常见的考点是遍历序列推导。比如已知前序遍历和中序遍历,求后序遍历。这类题的解法其实很固定:前序遍历的第一个节点一定是根节点,然后在中序遍历里找到根节点,就能把左右子树划分出来,递归处理。我在刷题时给自己总结了一句口诀:“前序找根,中序分界,递归切分”。记住这个思路,不管是求后序还是求层序,都能应对。

动态规划也是必考项。腾讯喜欢出经典背包、最长公共子序列、爬楼梯这类题目。选择题里一般不会让你完整写状态转移方程,但会考“dp数组某个位置的值是多少”或者“状态转移方程应该是哪个选项”。这种题丢分的原因通常是做题太少,状态定义不熟练。以爬楼梯为例,状态转移方程其实非常直观:dp[i] = dp[i-1] + dp[i-2],因为到达第i阶只能从第i-1阶或第i-2阶迈上来。但考场上题目稍微包装一下,比如加上“不能连续走两步”这种限制,很多人就懵了。我的建议是,刷动态规划题不要追求数量,而是把常见几种模型(线性DP、区间DP、背包、LIS/LCS)的状态定义和转移逻辑彻底搞懂。

2.3 操作系统与网络基础:原理比记忆更重要

操作系统和计算机网络在这套题里占的比重虽然没有C++大,但绝对是拉分项。操作系统爱考的点包括进程与线程的区别、死锁的四个必要条件、虚拟内存与分页、进程间通信方式。这些内容只看书不刷题,很容易产生“我懂了”的错觉,真到做题时才发现掌握得不够扎实。

举一个经典的例子:进程和线程的区别。很多同学能背出“进程是资源分配的最小单位,线程是CPU调度的最小单位”,但一旦考到“多线程共享哪些资源、独占哪些资源”就开始含糊。线程共享进程的地址空间、全局变量、文件描述符、信号处理器,但每个线程有自己的栈、寄存器和程序计数器。这个点反复出现在校招笔试里,腾讯也不例外。

网络部分,TCP三次握手是雷打不动的考点。选择题通常考“第三次握手发送的报文段确认号是多少”或“握手过程中各端状态如何变化”。还有可能结合SYN Flood攻击来考,问你为什么需要第三次握手。理解三次握手的核心在于确认双方收发能力都正常,同时防止旧连接请求的残留。SYN Flood就是利用不完整的握手过程来发起攻击,如果服务端收到大量SYN请求后,为每个请求分配资源并等待ACK,就会导致资源耗尽。

我还记得这套题里有关于TCP和UDP区别的选择题,题目本身不难,但选项很刁钻。比如“UDP是否可靠”“TCP是否面向字节流”“UDP是否有拥塞控制”。这些都是送分题,但如果不仔细看选项,很容易被类似的表述迷惑。复习的时候最好把TCP的可靠传输机制(确认、重传、流量控制、拥塞控制)和UDP的特点整理成一张对比表,考前过一遍,基本不会丢分。

3. 经典题型实操拆解:从读题到写出答案

3.1 细节题:运算符优先级与类型转换

腾讯笔试里有一类题,看起来简单,但正确率往往很低,就是运算符优先级和隐式类型转换。这类题考察的不是会不会编程,而是有没有真正记住语言的底层规则。

举一个高频例子:

int a = 5; int b = (a++) + (++a);

问 a 和 b 的值分别是多少。这个问题在不同编译器下可能有不同结果,C++标准里这种“在同一表达式中多次修改同一变量”的行为是未定义的,但很多笔试选择题会忽略这一点,给一个“标准答案”。实际刷题时遇到这种题,最好的策略是记住常见优先级规律,但对于未定义行为的代码,要能识别出题目本身不严谨。

运算符优先级有个流传很广的口诀:“单目 > 算术 > 移位 > 关系 > 位 > 逻辑 > 赋值 > 逗号”。但光背口诀不够,更重要的是做题时养成加括号的习惯。我在笔试时遇到不确定的表达式,会先在草稿纸上把优先级高的部分先算出来,再逐步代入,避免凭感觉直接选答案。

隐式类型转换也是高频考点,尤其是整型提升和算术转换。比如:

unsigned int a = 1; int b = -1; if (a > b) { printf("a > b\n"); } else { printf("a <= b\n"); }

这段代码输出什么?答案是 a > b。原因是在比较时,int 会被隐式转换为 unsigned int,-1 变成了 0xFFFFFFFF,也就是 4294967295,所以 a > b 不成立,输出 a <= b。很多人在这个基础题上翻车,不是不会,而是没意识到类型转换的时机。遇到这种题,先看两边的类型是否一致,如果不一致,一定要先转换再比较。

3.2 算法题:从递推公式到边界条件

笔试里如果出现简答或编程题,动态规划和字符串处理是主流方向。腾讯2016这套题我记得有一道比较有代表性的字符串相关问题,核心是求最长公共子串或最长公共子序列。很多人在拿到这类题后第一反应是“这题我见过”,但真下手写的时候,往往卡在dp数组的初始化上。

最长公共子序列的状态转移方程是这样的:

if (s1[i] == s2[j]) { dp[i][j] = dp[i-1][j-1] + 1; } else { dp[i][j] = max(dp[i-1][j], dp[i][j-1]); }

这里有个细节特别容易出错:dp数组的下标是从1开始还是从0开始。如果直接从0开始,那么处理i=0或j=0时会出现越界。最简单的做法是让dp数组多开一行一列,把dp[0][j]和dp[i][0]全部初始化为0,这样递推时就不需要额外判断边界。这个技巧在刷题时省了很多时间,我在笔试里也是这样处理的。

边界条件不仅出现在DP里,也出现在二叉树、链表的题目里。比如求二叉树深度时,递归出口是“节点为空则返回0”,很多同学会写成返回1,导致结果偏大。这些小错误在选择题里不会直接暴露,但如果考场上让你写代码,边界条件就是最容易被扣分的地方。我给自己定的规矩是:任何递归函数先写终止条件,任何循环先考虑边界索引,养成肌肉记忆。

3.3 排序算法:稳定性和复杂度对比

排序算法是腾讯笔试的常客,尤其喜欢考“哪些排序算法是稳定的”“最坏时间复杂度是O(n²)的排序有哪些”“堆排序为什么不稳定”这类对比型问题。

这里给一张我当年整理的速查表,建议直接背下来:

算法平均时间复杂度最坏时间复杂度空间复杂度稳定性
冒泡排序O(n²)O(n²)O(1)稳定
选择排序O(n²)O(n²)O(1)不稳定
插入排序O(n²)O(n²)O(1)稳定
希尔排序O(n^1.3)O(n²)O(1)不稳定
归并排序O(n log n)O(n log n)O(n)稳定
快速排序O(n log n)O(n²)O(log n)不稳定
堆排序O(n log n)O(n log n)O(1)不稳定

稳定性这个概念,字面意思就是“相等元素的相对顺序在排序后保持不变”。为什么有的场景必须用稳定排序?典型场景是成绩排名,按总分排完还要保持相同分数下按学号的原始顺序。理解了应用场景,就不容易记混。

还有一个常见的变体题:如果要求“在O(n)时间内把0和1分开”,或者“把负数放左边、正数放右边”,这其实是快速排序中 partition 操作的应用。很多选择题不会直接问快速排序怎么写,而是问“一趟快排之后,某个元素的位置会在哪里”,本质是在考察 partition 后的结果。我建议把快排的单趟过程亲手模拟一遍,比背十遍代码都管用。

4. 备考经验与踩坑指南

4.1 刷题顺序:先基础后综合

我在准备这类笔试时走过一段弯路,一开始直接刷整套卷子,结果错得一塌糊涂,对完答案发现很多题不是不会,而是基础知识有漏洞。后来我调整了策略:先把每个科目的高频考点过一遍,再针对薄弱点刷专项题,最后才做整套模拟题。

具体来说,我会把时间分成三个阶段:

  • 第一阶段(基础巩固):梳理C++语法要点,尤其是内存管理和面向对象部分;把常见数据结构从头实现一遍,包括链表、栈、队列、二叉树;操作系统和网络只看高频考点,不追求面面俱到。
  • 第二阶段(专项突破):针对每个高频考点刷题,比如连续刷20道数组指针题、20道二叉树遍历题、20道动态规划题。刷完后总结出题套路和常见陷阱,形成自己的错题本。
  • 第三阶段(成套模拟):严格按照考试时间做整套题,做完不仅看正确率,还要复盘每道错题背后的知识点漏洞。

对于时间比较紧的同学,我的建议是优先搞定C++基础、经典排序算法、链表和二叉树,这几个板块出题概率高,回报比也最大。

4.2 错题本的正确打开方式

说到错题本,我曾踩过一个坑:把错题抄一遍、答案写上去,然后就再也没有翻过。这种错题本除了感动自己,没有任何用处。正确的做法是,错题本上不写详细解析,只写“题目考点 + 错误原因 + 正确结论”,隔几天遮住答案重新做一遍,直到连续两次做对为止。

举个例子,如果我在“int与unsigned int比较”这类题上栽了跟头,我会在错题本上记下:

  • 考点:隐式类型转换规则
  • 错误原因:忽略整型提升
  • 正确结论:有符号与无符号比较时,有符号数会转为无符号数

这样做的意义在于,把一道错题抽象成一个知识卡片,而不是机械地记住某道题的答案。大厂笔试的题目几乎不会原封不动地重复,但考点就那么些,抽象成卡片后,遇到变体题也能一眼识别出本质。

4.3 考场上最容易犯的错误

把我自己和其他同学的经验汇总一下,考场上常见的丢分点有这几类:

  • 审题不仔细,选项没看完就选。腾讯的选项经常有“A和B都正确”“以上说法都不对”这种组合型选项,只看前两个选项很容易选错。
  • 在计算题上死磕,浪费时间。有些选择题看似要算很多步,其实可以用排除法快速定位正确答案,先把明显错误的选项排除,再在剩下的选项里精算。
  • 遇到不会的题乱蒙,但忽略了“少得分策略”。如果笔试有倒扣分规则,不会的题宁可不选也不要瞎蒙;如果没有倒扣分,可以凭常识猜一个,但不要因此影响后面的答题节奏。

我个人的习惯是:整套卷子先做一遍,遇到卡壳的题先标记,不在当场纠结。等第一遍做完,再回头处理标记的题目。这样能保证会做的题都拿到分,不会因为某一题耗时太久而导致后面会做的题没时间。

4.4 长期备考的额外建议

如果你准备时间还比较充裕,我强烈建议你不要只刷题,而是把《C++ Primer》中关于内存、对象、模板的部分精读一遍,把《深入理解计算机系统》中关于链接、虚拟内存、异常控制流的部分扫一遍。这些书虽然厚,但读完再看笔试题,很多题不用猜就能直接推理出答案。

再一个建议就是多写代码。笔试里有些知识点,单看解析觉得懂了,一旦让你动手实现就会露馅。比如让你实现一个String类(包含构造、析构、拷贝构造、赋值运算符),这道经典面试题能暴露出很多问题:析构函数有没有加virtual、拷贝构造有没有深拷贝、赋值运算符有没有处理自赋值。笔试可能不直接考这么完整的代码题,但里面涉及的每一个点,都可能在选择题里出现。

5. 从这套题反推面试准备方向

5.1 为什么笔试后紧接着是问“项目亮点”

笔试只是第一关,腾讯的面试往往会在项目经历上深挖。笔试基础题做得好,说明你有扎实的底子,但面试官更关心的是你能不能把基础能力应用到实际项目中。所以我在准备笔试的同时,也在复习自己的项目,重点想清楚几个问题:

  • 项目里最有技术含量的模块是哪个?它解决了什么实际问题?
  • 用到了哪些数据结构、算法或者设计模式?为什么这么选?
  • 如果数据量扩大十倍,你的方案还成立吗?瓶颈在哪里?

刷题和项目复盘并不是割裂的。比如你在项目里处理过大量日志数据,那就可以把哈希、排序、多线程这些知识点串联起来讲,比单纯背概念有说服力得多。

5.2 笔试是敲门砖,不是终点

说到最后,我想提醒一点:不要因为一套笔试题做得不好就否定自己。这套题覆盖面广,但每一道题背后,都是可以在几个月内通过系统复习补起来的。反过来,如果笔试做得顺手,也别飘,因为真正的战场是面试,笔试只是告诉面试官“你可以来聊聊”。

我当年刷完这套题之后,最大的感受是:基础不牢,地动山摇。很多业务代码写久了,人会变得“会用但不懂”,看答案觉得简单,自己选就错。只有把那些底层原理真正吃透,做题才不是靠猜,而是靠推理。这也是我后来每次带校招生,都让他们先刷这类经典笔试的原因——它像一面镜子,清清楚楚照出你的知识短板在哪里。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询