2026.09.20-深圳小厂Rust全栈面经与复盘

2026.09.20-深圳小厂Rust全栈面经与复盘

最后更新:


906 字 约 5 分钟

C++八股

  • 面试官:请你介绍一下为什么C++基类的析构函数要声明为虚函数

这个倒是还记得,如果不声明为虚函数,在析构子类对象的之后就会调用基类的析构函数,子类自身持有的资源无法被释放,造成内存泄漏

  • 面试官:介绍一下C++的值类型

这里只记得左值和右值,然后扯了一堆生命周期相关的乱七八糟的东西,但实际上就是左值、将亡值、右值这三种

其中左值就是能够用&取到地址的变量,有固定的内存地址;纯右值就是临时拿来用的,取不到地址,用完即销毁;将亡值介乎两者之间,既有自己的内存地址,又即将被销毁或者掏空资源,专门触发移动语义,典型代表就是std::move(x)的返回值

  • 面试官:讲讲左值引用和右值引用的区别

这里更是忘得差不多了,但其实很简单

左值引用用的&,绑定的就是有身份的长期变量,即为左值,然后主要用于防止触发拷贝;右值引用用的&&,绑定的是即将销毁的临时对象,即为右值,主要用于资源转移

  • 面试官:讲讲移动语义

这个就是在C++11中引入的std::move(),需要注意的是它并不移动任何东西,而是一个类型转换器,将一个有名字的变量左值临时转换为右值,这样就可以触发移动构造,进行资源所有权的转移

后面就说了些移动构造函数之类的,然后面试官开始给我讲课了,我讲的不清楚的地方他给我理了一遍…人是真的好


C++阅读代码题

然后面试官给了一段代码来看:

C++
void appendLast(const std::vector<int>& vec, size_t count) {
    if (vec.empty()) {
        return;
    }

    const int* tail = vec.back();
    for (size_t i = 0; i < count; ++i) {
        vec.push_back(*tail);
    }
}

让我看一下有什么问题

首先想到的是这样push_back()会触发频繁扩容内存分配,导致性能下降,面试官认可,但提示还有一个正确性问题

然后仔细想了一下,发现内存重新分配,原来的tail指针指向的内存地址很可能已经失效

然后面试官追问:如果你是push_back()这个函数的设计者,你会怎么处理扩容

我想了一下,讲了指数扩容,然后重新分配堆内存,但是这里表述有点不太行,讲成是C++这边应用层直接分配堆内存了,应该是申请操作系统内核给它重新分配


手撕

做了一道求数组中下标三元组 (i,j,k)(i, j , k) 个数满足 ai+aj+ak<targeta_i + a_j + a_k < target 的题目,但是感觉也是太久没写题了,最后双指针卡在指针移动搞反了,最后面试官提醒才换回来,勉强算做出来了

C++
sort(a, a + n);
int ans = 0;

for (int i = 0; i < n; ++i) {
    int maxx = target - a[i];
    int l = i + 1, r = n - 1;

    while (l < r) {
        if (a[l] + a[r] < maxx) {
            ans += r - l;
            ++l;
        } else {
            --r;
        }
    }
}

简历拷打

最后是问了一下犀牛鸟那个开源经历的相关问题,但是时间也过得太久,有点模糊了,Fts5的语法也不太熟,举不出例子来,现在复习一下

首先来看这个问题是什么,其实就是很简单的一个小问题,在bulidFtsQuery()函数中,需要对用户的输入先进行分词,分词完之后构建出一个FTS5查询语句,传到下一层进行查询

后面的SQL已经做了防注入,FTS5查询语句经过原来的处理之后,先分词再删除双引号,也比较难进行注入了,但是主要的问题就是会改变用户的查询语义,比如说用户输入的foo"bar经过原来的处理之后会变成foobar查询,改变实际的搜索内容,然而用户本来的意图是形成"foo", "bar"这样的FTS5 phrase语句

然后我的这个PR实现的就是,原来是去掉双引号,我这里把双引号加倍,即"变成"",这样一来foo"bar就会变成foo""bar,然后用户输入的OR, NEAR这种查询语句也都会被双引号包围,变成普通的查询词

评论

评论会在审核后展示

查看原图