虎牙C++ 一面

1、自我介绍

介绍了一下我自己啥情况,之前在哪个公司实习过,主要参与 C++ 后端相关开发工作。 实习期间我做过消息处理/服务端模块开发,参与了功能迭代、问题排查和一部分性能优化工作。 技术栈方面,我主要掌握 C/C++,熟悉 STL、Linux 开发环境、网络编程(TCP/IP)、多线程与并发编程,了解常用的数据结构与算法,也用过 MySQL、Redis 这类常见组件。 整体上我偏工程实践,比较关注代码质量、稳定性和性能,想在 C++ 后端方向继续深入。

2、单例模式和工厂模式的作用

单例模式:保证一个类全局只有一个实例,适合日志、配置中心、线程池这种“全局只要一个”的对象。 工厂模式:把对象创建过程封装起来,调用方不用关心具体创建哪个类,便于解耦和扩展。

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

class Product {
public:
    virtual ~Product() = default;
    virtual void run() = 0;
};

class ProductA : public Product {
public:
    void run() override { cout << "ProductA running\n"; }
};

class ProductB : public Product {
public:
    void run() override { cout << "ProductB running\n"; }
};

class Factory {
public:
    static unique_ptr<Product> create(int type) {
        if (type == 1) return make_unique<ProductA>();
        return make_unique<ProductB>();
    }
};

3、懒汉模式的实例化细节(C++98 和 C++11)

懒汉模式是第一次使用时才创建实例。 C++98 中局部静态变量初始化不是线程安全的,需要手动加锁。 C++11 开始函数内局部静态变量初始化是线程安全的,推荐这种写法。

C++98 写法(加锁版):

#include <pthread.h>

class Singleton98 {
private:
    Singleton98() {}
    Singleton98(const Singleton98&);
    Singleton98& operator=(const Singleton98&);
    static Singleton98* instance_;
    static pthread_mutex_t mutex_;

public:
    static Singleton98* getInstance() {
        pthread_mutex_lock(&mutex_);
        if (instance_ == 0) {
            instance_ = new Singleton98();
        }
        pthread_mutex_unlock(&mutex_);
        return instance_;
    }
};

Singleton98* Singleton98::instance_ = 0;
pthread_mutex_t Singleton98::mutex_ = PTHREAD_MUTEX_INITIALIZER;

C++11 推荐写法:

class Singleton11 {
public:
    static Singleton11& getInstance() {
        static Singleton11 instance; // C++11 线程安全初始化
        return instance;
    }

    Singleton11(const Singleton11&) = delete;
    Singleton11& operator=(const Singleton11&) = delete;

private:
    Singleton11() = default;
};

4、用过哪些锁

常用:std::mutex、std::recursive_mutex、std::timed_mutex、std::shared_mutex(C++17)。 常搭配:std::lock_guard、std::unique_lock(RAII 管理锁)。 工程里一般优先 mutex + lock_guard,读多写少场景再用 shared_mutex。

#include <iostream>
#include <thread>
#include <mutex>
#include <shared_mutex>
using namespace std;

int counter = 0;
mutex mtx;

void add() {
    lock_guard<mutex> lk(mtx);
    ++counter;
}

shared_mutex rw_mtx;
int data_val = 0;

void reader() {
    shared_lock<shared_mutex> lk(rw_mtx);
    cout << "read: " << data_val << "\n";
}

void writer() {
    unique_lock<shared_mutex> lk(rw_mtx);
    ++data_val;
}

5、多态是如何实现的

C++ 运行时多态通过虚函数实现。 基类函数加 virtual,子类重写后,通过基类指针或引用调用时会发生动态绑定。 底层依赖虚函数表(vtable)和虚表指针(vptr)。

#include <iostream>
using namespace std;

class Base {
public:
    virtual ~Base() = default;
    virtual void speak() { cout << "Base\n"; }
};

class Derive : public Base {
public:
    void speak() override { cout << "Derive\n"; }
};

int main() {
    Base* p = new Derive();
    p->speak(); // 输出 Derive
    delete p;
    return 0;
}

6、虚函数表和虚表指针是在堆上还是栈上

虚函数表(vtable)通常在只读数据段。 虚表指针(vptr)属于对象本身,跟对象存储位置一致:对象在栈上,vptr 在栈对象里;对象在堆上,vptr 在堆对象里。

7、哈希表的理解

哈希表通过哈希函数把 key 映射到数组下标,查找/插入/删除平均时间复杂度 O(1)。 关键点是哈希均匀性、冲突处理(拉链法或开放寻址)、负载因子和扩容。 最坏情况下会退化到 O(n)。C++ 常用 unordered_map。

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

int main() {
    unordered_map<string, int> mp;
    mp["alice"] = 95;
    mp["bob"] = 88;

    if (mp.find("alice") != mp.end()) {
        cout << mp["alice"] << "\n";
    }
    mp.erase("bob");
    return 0;
}

8、项目介绍

我在实习里做的是一个直播间消息处理相关的小模块,主要是把上游来的事件做清洗、分发和落库,目标是让链路更稳定、延迟更低。 我主要负责这个模块的开发和维护,做了三件比较关键的事:把串行处理改成线程池并发消费;拆分高频锁、缩小临界区;补齐监控和日志,方便排查抖动。 技术上主要用 C++、多线程、STL 容器和内部 RPC/存储接口。 最终效果是高峰期处理更稳,超时率明显下降,P99 延迟也比之前低了一截。

9、项目中遇到的困难

当时高峰期会出现偶发卡顿,平均延迟还行,但 P99 会突然拉高。 一开始怀疑网络,后来结合监控和火焰图定位到本地瓶颈:共享 map 锁竞争激烈,同时同步日志写入拖慢了主流程。 后面做了几步优化:热点读写分离、减少大锁持有时间、非关键日志异步化,再加上限流和队列长度告警。 优化后抖动明显减少,P99 更稳定,线上报警次数也下降了。这个问题也让我后面做并发模块时会优先关注锁粒度和慢路径。

10、反问

我问了几个问题: ① 我这次回答整体怎么样,哪些地方还不够到位,后续我可以重点改进。 ② 如果有机会进组,前 1-3 个月对新人的预期是什么,会不会有师兄带、代码评审和学习路线。 ③ 组里平时做性能优化最常用哪些工具、排查流程一般怎么走。

C++面试总结 文章被收录于专栏

本专栏系统梳理C++面试高频考点,从基础语法、内存管理、STL与设计模式,到操作系统与项目实战,结合真实面试题深度解析,帮助开发者高效查漏补缺,提升技术理解与面试通过率,打造扎实的C++工程能力。

全部评论

相关推荐

02-16 01:39
南昌大学 Java
重剑Ds:感觉不太可能 后端都减飞了 根本不缺人
点赞 评论 收藏
分享
02-14 07:38
已编辑
门头沟学院 Java
2.4&nbsp;一面2.6&nbsp;二面2.9&nbsp;三面(hr面)2.13&nbsp;oc1.15号收到面试电话那会就开始准备,因为一开始没底所以选择推迟一段时间面试,之后开始准备八股,准备实习可能会问的东西,这期间hot100过了有六七遍,真的是做吐了快,八股也是背了忘,忘了背,面经也看了很多,虽然最后用上的只有几道题,可是谁知道会问什么呢自从大二上开始学java以来,一路走来真的太痛了,一开始做外卖,点评,学微服务,大二下五六月时,开始投简历,哎,投了一千份了无音讯,开始怀疑自己(虽然能力确实很一般),后来去到一家小小厂,但是并不能学到什么东西,而且很多东西都很不规范,没待多久便离开,大二暑假基本上摆烂很怀疑自己,大三上因为某些原因开始继续学,期间也受到一俩个中小厂的offer,不过学校不知道为啥又不允许中小厂实习只允许大厂加上待遇不太好所以也没去,感觉自己后端能力很一般,于是便打算转战测开,学习了一些比较简单的测试理论(没有很深入的学),然后十二月又开始继续投,java和测开都投,不过好像并没有几个面试,有点打击不过并没有放弃心里还是想争一口气,一月初因为学校事比较多加上考试便有几天没有继续投,10号放假后便继续,想着放假应该很多人辞职可能机会大一点,直到接到字节的面试,心里挺激动的,总算有大厂面试了,虽然很开心,但同时压力也很大,心里真的很想很想很想进,一面前几天晚上都睡不好觉,基本上都是二三点睡六七点醒了,好在幸运终于眷顾我一次了(可能是之前太痛了),一面三十几分钟结束,问的都不太难,而且面试官人挺好但是有些问题问的很刁钻问到了测试的一些思想并不是理论,我不太了解这方面,但是也会给我讲一讲他的理解,但是面完很伤心觉得自己要挂了。但是幸运的是一面过了(感谢面试官),两天后二面,问的同样不算难,手撕也比较简单,但也有一两个没答出来,面试官人很好并没有追问,因为是周五进行的二面,没有立即出结果,等到周一才通知到过了,很煎熬的两天,根本睡不好,好在下周一终于通知二面过了(感谢面试官),然后约第二天三面,听别的字节同学说hr面基本上是谈薪资了,但是我的并不是,hr还问了业务相关的问题,不过问的比较浅,hr还问我好像比较紧张,而且hr明确说了还要比较一下,我说我有几家的面试都拒了就在等字节的面试(当然紧张,紧张到爆了要),三面完后就开始等结果,这几天干啥都没什么劲,等的好煎熬,终于13号下午接到了电话通知oc了,正式邮件也同时发了,接到以后真的不敢信,很激动但更重要的是可以松一口气了,可以安心的休息一下了终于可以带着个好消息过年了,找实习也可以稍微告一段落了,虽然本人很菜,但是感谢字节收留,成为忠诚的节孝子了因为问的比较简单,面经就挑几个记得的写一下一面:1.实习项目的难点说一下2.针对抖音评论设计一下测试用例3.手撕:合并两个有序数组二面:1.为什么转测开2.线程进程区别,什么场景适合用哪个3.发送一个朋友圈,从发出到别人看到,从数据流转的角度说一下会经历哪些过程4.针对抖音刷到广告视频设计测试用例5.手撕:无重复字符的最长字串
查看8道真题和解析
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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