25届校招深信服技术岗一面面经|基础为王,附核心考点+详细回答思路

本次分享一位25届应届生的深信服技术岗一面面经,面试整体难度偏基础,核心考察计算机核心基础与算法能力,希望能为同届校招同学提供参考。

整理了100+大厂面经经验,希望可以帮到大家。

一、学生个人情况介绍

本次分享的面经来自25届应届毕业生,应聘深信服校招技术岗,本次为一面环节。该同学反馈面试体验良好,无超纲冷门考点,考察重点集中在C++编程语言、计算机网络、操作系统、SQL基础经典手撕算法题,是典型的技术岗基础能力验证型面试。

二、面试企业和部门介绍

1. 企业介绍

深信服科技股份有限公司是国内头部的网络安全、云计算与IT基础设施解决方案提供商,业务覆盖政企、金融、教育、医疗等多个领域。校招技术岗招聘中,深信服高度重视候选人的计算机基础功底(网络、操作系统)、编程语言实战能力(以C/C++为主)和算法思维,核心考察“基础是否扎实”而非“冷门知识储备”。

2. 面试部门

本次面试为深信服通用技术岗一面,未明确细分具体业务部门,所有问题均围绕通用技术能力展开,无针对性的业务场景问题,聚焦基础能力验证。

三、面试核心内容与回答思路

面试内容分为五大模块,以下为每个问题的提问方向、详细回答思路及核心要点:

模块一:C++(核心编程语言考察)

C++是本次面试的重点考察方向,问题均为技术岗高频基础考点,注重“理解原理+能落地解释”。

问题1:介绍C++面向对象的三大特性

回答思路:先总述三大特性名称,再分别拆解每个特性的“定义+核心价值+通俗示例”,让回答有层次、不空洞。核心回答:C++面向对象的三大核心特性是继承、封装、多态,三者共同支撑“代码复用、抽象化、逻辑灵活”的编程思想:

  • 继承:让子类获取父类的属性和方法,无需重复编写原有代码,同时可扩展新功能(如“动物”父类定义通用行为,“猫/狗”子类继承后扩展“叫”的具体逻辑);
  • 封装:将事物的属性和方法抽象为类,通过public/private/protected控制访问权限,对不可信的外部隐藏核心数据(如类的私有成员仅能被内部方法修改,避免外部误操作);
  • 多态:同一消息发送给不同对象,执行不同逻辑——编译时多态通过函数重载实现,运行时多态通过虚函数/纯虚函数实现(如父类指针指向子类对象,调用同一方法时执行子类逻辑)。

问题2:C++ 11有哪些新特性?

回答思路:优先列举“高频实用”的新特性,每个特性说明“解决的问题+简单使用示例”,避免仅罗列名词。核心回答:C++11是C++的里程碑版本,新增特性大幅提升开发效率,核心常用的有:

  • nullptr:替代原有NULLNULL本质是0,易引发指针/整数类型混淆),专门表示空指针,类型更安全;
  • 类型推导关键字:auto让编译器自动推导变量类型(如auto i = 10;推导为int),decltype推导表达式类型,减少复杂类型的冗余书写;
  • 基于范围的for循环:简化容器遍历,如for(auto& i : res){}可直接遍历数组/容器,无需手动控制下标;
  • Lambda表达式:支持定义匿名函数,适用于临时简单逻辑(如容器排序时直接写排序规则);
  • 右值引用与move语义:解决临时对象的拷贝效率问题,通过std::move实现资源转移,减少内存拷贝;
  • 其他:类/结构体初始化列表(struct A{int a;}; A a{10};)、std::forward_list(单向链表,节省内存)等。

问题3:hashtable中解决冲突有哪些方法?

回答思路:先说明哈希冲突的本质(不同key映射到同一地址),再分点介绍每种方法的“核心逻辑+优缺点”,突出工业界常用方案。核心回答:哈希冲突是“不同key经哈希函数计算后得到同一数组下标”,常见解决方法有4种:

  • 线性探测:冲突时向后依次找空位(表尾则回到表头),实现简单但易出现“连续聚集”,降低查找效率;
  • 开链法(拉链法):每个哈希位置维护一个链表,冲突的key插入对应链表,无聚集问题,是工业界主流方案(如C++ unordered_map底层实现);
  • 再散列:冲突时用另一哈希函数重新计算地址,直到找到空位,避免聚集但增加哈希计算开销;
  • 二次探测:冲突时按平方步长(1²、2²、3²…)找空位,相比线性探测减少聚集,若步长为随机数则为伪随机探测。

问题4:区分int *p[10]int (*p)[10](指针数组 vs 数组指针)

回答思路:结合“运算符优先级”拆解语法,明确“核心是数组”还是“核心是指针”,配合通俗解释。核心回答:区分的关键是[]优先级高于*,核心看“本质是数组还是指针”:

  • int *p[10]:指针数组——先构成数组p[10],数组的每个元素是int*类型(指向int的指针),核心是“数组”;
  • int (*p)[10]:数组指针——()提升*优先级,先构成指针p,该指针指向“包含10个int元素的数组”,核心是“指针”。

模块二:操作系统

操作系统考察聚焦“内存管理”和“数据存储”,均为技术岗必考点,注重“对比记忆+原理理解”。

问题5:堆和栈的区别

回答思路:从“管理方式、内存机制、空间大小、碎片、生长方向、分配方式、效率”7个维度对比,结合通俗解释辅助理解。核心回答(表格梳理)

管理方式

程序员手动控制(

new/delete

),易内存泄漏

编译器自动管理,出作用域自动释放

内存管理机制

基于空闲链表分配,找首个足够大的内存块

连续内存,剩余空间足够则分配,否则栈溢出

空间大小

不连续,受虚拟内存限制(32位系统理论4G),空间大且灵活

连续,大小固定(Windows默认2M),空间小

碎片问题

频繁

new/delete

易产生内存碎片,降低效率

先进后出,进出一一对应,无碎片

生长方向

向上(高地址方向)

向下(低地址方向)

分配方式

仅动态分配

静态分配(局部变量)+动态分配(

alloca

函数),均自动释放

分配效率

函数库实现,机制复杂,效率低

系统底层支持(专用寄存器/指令),效率高

问题6:大小端存储是什么意思?如何区分?

回答思路:先定义大小端,结合数值示例说明存储方式,再给出两种可运行的代码判断方法,解释核心原理。核心回答

1. 大小端定义

大小端是多字节数据的内存存储顺序,核心区别:

  • 大端存储:高字节存低地址(符合人类阅读习惯,如0x12345678,低地址存0x12);
  • 小端存储:低字节存低地址(主流操作系统采用,如0x12345678,低地址存0x78); 注:网络传输用大端,Socket编程需将主机小端转为网络大端。
2. 代码判断方法

方法一:强制类型转换(利用int转char仅保留低地址字节)

#include <iostream>
using namespace std;
int main() {
    int a = 0x1234;
    char c = (char)a; // 仅保留低地址字节
    if (c == 0x12) cout << "大端" << endl;
    else if (c == 0x34) cout << "小端" << endl;
    return 0;
}

方法二:联合体(利用成员共享内存的特性)

#include <iostream>
using namespace std;
union endian {
    int a;    // 4字节,与ch共享内存
    char ch;  // 仅占用a的低地址部分
};
int main() {
    endian val;
    val.a = 0x1234;
    if (val.ch == 0x12) cout << "大端" << endl;
    else if (val.ch == 0x34) cout << "小端" << endl;
    return 0;
}

模块二:计算机网络

网络考察聚焦“TCP可靠性”和“会话管理”,均为校招高频考点,注重“机制理解+对比分析”。

问题7:TCP是如何保证可靠传输的?

回答思路:从“确认重传、数据校验、分片排序、流量控制、拥塞控制”5个维度展开,每个机制说明“作用+实现方式”,对比UDP突出TCP的可靠性。核心回答:TCP通过5大核心机制保证可靠传输:

  1. 确认与重传:接收方收到报文返回ACK确认,发送方超时未收到则重传;
  2. 数据校验:TCP报文头含校验和,接收方验证报文是否损坏,损坏则丢弃并触发重传;
  3. 分片与排序:按MTU合理分片,接收方缓存未按序分片,排序后交给应用层(UDP分片丢失则丢弃整个数据报);
  4. 流量控制:基于滑动窗口,接收方通过窗口大小告知发送方接收能力,避免接收方处理不及时丢包;
  5. 拥塞控制:基于拥塞窗口,通过慢启动、拥塞避免等算法,减少网络拥塞时的发送速率。

问题8:Cookies和Session分别存放在哪里?

回答思路:先明确存储位置,再补充“安全性+数据大小”等延伸点,让回答更完整。核心回答:Cookie和Session是维持会话的核心机制,核心区别在存储位置:

  • Cookie:存储在客户端(浏览器),是服务器发送的小型文本文件,大小受限(约4KB),安全性低(易被篡改),可设置过期时间;
  • Session:存储在服务端(内存/数据库/缓存),服务器生成唯一SessionID并通过Cookie传递给客户端,数据更安全、无大小限制,适用于存储敏感信息(如登录状态)。

模块三:SQL

考察分组统计的基础语法,聚焦GROUP BY的核心使用,注重“需求拆解+语法正确性”。

问题9:班级成绩表(grades),区分sex为male和female,如何写SQL?

回答思路:先明确需求(按性别分组,统计人数+平均分),再给出SQL语句,解释核心关键字的作用。核心回答:需求是按性别(male/female)分组,统计每组的学生数量和平均成绩,SQL语句及解释如下:

SELECT 
    sex,  -- 分组维度:性别
    COUNT(*) AS total_students,  -- 统计每组学生数
    AVG(score) AS average_score  -- 计算每组平均分
FROM grades
WHERE sex IN ('male', 'female')  -- 筛选有效性别(可选)
GROUP BY sex;  -- 按性别分组

模块四:手撕算法(现场编码)

算法题考察经典题型,注重“代码逻辑正确+边界条件处理”,以下为完整可运行代码及思路:

算法题1:手写快速排序

核心思路:分治思想——选基准值→分区(小于基准放左,大于放右)→递归排序左右子数组,注意边界条件(low >= high时终止递归)。

#include <iostream>
#include <vector>
using namespace std;

// 分区函数:返回基准值的正确下标
int partition(vector<int>& nums, int low, int high) {
    int pivot = nums[high]; // 选最右元素为基准
    int i = low - 1; // 小于基准的区域边界
    for (int j = low; j < high; j++) {
        if (nums[j] <= pivot) {
            i++;
            swap(nums[i], nums[j]);
        }
    }
    swap(nums[i+1], nums[high]); // 基准值归位
    return i + 1;
}

// 快速排序递归函数
void quickSort(vector<int>& nums, int low, int high) {
    if (low < high) { // 边界条件:子数组长度>1才排序
        int pi = partition(nums, low, high);
        quickSort(nums, low, pi - 1); // 排序左子数组
        quickSort(nums, pi + 1, high); // 排序右子数组
    }
}

// 测试示例
int main() {
    vector<int> nums = {3,1,4,1,5,9,2,6};
    quickSort(nums, 0, nums.size()-1);
    for (int num : nums) cout << num << " "; // 输出:1 1 2 3 4 5 6 9
    return 0;
}

算法题2:判断链表是否有环

核心思路:快慢指针法(龟兔赛跑)——快指针走2步,慢指针走1步,若相遇则有环;若快指针到链表尾则无环,注意空链表/单节点的边界条件。

#include <iostream>
using namespace std;

// 链表节点定义
struct ListNode {
    int val;
    ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};

// 判断链表是否有环
bool hasCycle(ListNode *head) {
    // 边界条件:空链表/单节点无环
    if (head == NULL || head->next == NULL) return false;
    ListNode* slow = head; // 慢指针:走1步
    ListNode* fast = head->next; // 快指针:走2步
    while (slow != fast) {
        if (fast == NULL || fast->next == NULL) return false; // 快指针到尾,无环
        slow = slow->next;
        fast = fast->next->next;
    }
    return true; // 相遇,有环
}

// 测试示例
int main() {
    // 构造有环链表:1->2->3->4->2
    ListNode* head = new ListNode(1);
    head->next = new ListNode(2);
    head->next->next = new ListNode(3);
    head->next->next->next = new ListNode(4);
    head->next->next->next->next = head->next; // 环指向2
    cout << (hasCycle(head) ? "有环" : "无环") << endl; // 输出:有环
    return 0;
}

四、总结

关键点回顾

  1. 面试难度:深信服技术岗一面以基础为主,无偏题怪题,核心考察C++、操作系统、计算机网络三大核心学科,SQL和算法为常规经典题;
  2. 备考重点:编程语言聚焦C++面向对象、指针、C++11特性,基础学科注重“原理理解”而非死记硬背,算法掌握快排、链表判环等经典题;
  3. 回答技巧:回答问题时先总述核心要点,再分点拆解,结合“通俗示例/应用场景”说明,避免仅罗列知识点。
全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务