腾讯互娱 C++开发 一面

1. cpp 的虚函数和纯虚函数

答案:虚函数是为了支持运行时多态。父类把成员函数声明为 virtual 之后,子类可以重写它,通过父类指针或引用调用时,会根据对象的真实类型决定执行哪个版本。纯虚函数是在虚函数声明后写上 = 0,表示这个函数只定义接口、不提供默认实现。只要类里存在纯虚函数,这个类通常就是抽象类,不能直接实例化,派生类如果不实现这些纯虚函数,也不能实例化。虚函数强调“可以重写”,纯虚函数强调“必须实现”。工程里纯虚函数经常用于定义接口层,比如网络连接接口、日志接口、存储接口。

代码:

#include <iostream>
using namespace std;

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

class Derived : public Base {
public:
    void f() override { cout << "Derived::f\n"; }
    void g() override { cout << "Derived::g\n"; }
};

int main() {
    Base* p = new Derived();
    p->f();
    p->g();
    delete p;
    return 0;
}

2. 虚函数的底层是怎么实现的

答案:主流编译器一般通过虚函数表实现多态。如果一个类里有虚函数,那么对象内部通常会有一个隐藏的虚表指针,指向该类对应的虚函数表。虚函数表里存的是虚函数入口地址。当通过基类指针调用虚函数时,程序不是直接静态绑定到某个函数,而是先找到对象中的虚表指针,再去虚表里查实际要调用的函数地址。所以虚函数调用比普通函数多了一次间接寻址,但换来了运行时的动态分派能力。多继承、虚继承场景下,对象布局和 this 指针调整会更复杂。

3. 说一下 C++ 里对象内存布局和内存对齐

答案:一个普通 C++ 对象通常包含它的非静态成员变量,如果类里有虚函数,还会额外有一个虚表指针。静态成员变量不放在对象实例里。内存对齐是为了让 CPU 更高效地访问数据,也为了满足硬件对某些类型访问边界的要求。编译器会根据成员类型的对齐要求插入 padding,所以类大小往往不是成员大小简单相加。这也是为什么调换成员顺序可能会影响 sizeof 结果。工程里如果对象数量很多,合理调整成员顺序能减少内存浪费。

代码:

#include <iostream>
using namespace std;

class A {
public:
    virtual void f() {}
    char c;
    int x;
    short y;
};

int main() {
    cout << sizeof(A) << endl;
    return 0;
}

4. defer 的执行顺序是什么样的

答案:多个 defer 会按照后进先出的顺序执行,也就是栈结构。谁最后被 defer 注册,谁最先执行。这个设计很适合做成对资源的释放,比如先加锁后解锁、先打开文件后关闭文件,执行顺序正好和申请顺序相反。另外要注意,defer 注册时会先计算参数,再延迟执行函数体。这个细节经常被拿来考。

代码:

package main

import "fmt"

func main() {
    defer fmt.Println(1)
    defer fmt.Println(2)
    defer fmt.Println(3)
}

5 在 for 循环里执行 defer 的结果是什么样的

答案:如果在 for 循环中不断写 defer,这些延迟调用不会在每轮循环结束时执行,而是会等整个函数返回时统一触发,并且仍然遵循后进先出。所以如果循环很多次,defer 会不断堆积,既影响执行顺序,也可能带来额外内存开销。这题常见陷阱还有循环变量捕获问题。如果闭包里直接引用循环变量,最终看到的值往往不是你直觉里每轮各自独立的那个值。

代码:

package main

import "fmt"

func main() {
    for i := 0; i < 3; i++ {
        defer fmt.Println(i)
    }
}

6. 想在每个循环结束后执行 defer 应该怎么做

答案:因为 defer的作用域是函数,不是循环体,所以如果想在每轮循环结束时就执行收尾动作,通常做法是把这一轮逻辑包装进一个匿名函数或者普通函数里

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

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

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

全部评论

相关推荐

其实Agent面试的核心都绕不开大模型理解、工具调用、流程编排还有工程落地这几块,不会太偏理论,更多是看你能不能把技术落到实处。首先肯定会问你对Agent的理解,比如它和普通大模型应用到底不一样在哪,要是说不出自主决策、记忆和工具调用这些关键点,大概率会被觉得底子不扎实。还会聊到主流的框架,比如LangChain或者LlamaIndex,问你用过没有,各自有什么优缺点,踩过哪些坑。然后技术层面会盯着工具调用和RAG这两个核心。比如怎么让Agent精准选对工具,调用失败了该怎么处理,会不会加重试机制或者异常兜底。RAG也是必聊的,比如它在Agent里能解决什么问题,怎么提升检索的准确率,用过哪些向量数据库,这些都得结合实际的使用经验说,光背概念可不行。还有记忆模块,短期记忆和长期记忆的区别,怎么存怎么取,这些细节也会被问到。作为Java工程师,面试官肯定会更关注你怎么把Agent和业务系统结合起来。比如怎么用Java调用大模型API,怎么对接公司现有的接口让Agent拥有实际业务能力,甚至会问你怎么解决大模型调用的延迟和限额问题,比如缓存、异步处理这些实际的优化手段。幻觉问题也是绕不开的,得说说你平时怎么通过事实校验、多轮反思来减少这种情况。项目经验这块特别重要,哪怕没做过正式项目,自己搭的Demo也能说。比如做过知识库问答Agent,或者代码调试助手,得讲清楚核心流程,遇到过什么难题,比如工具调用成功率低,或者检索结果不准,最后是怎么解决的。还会给你出一些实际场景题,比如让你设计一个电商客服Agent,怎么对接订单和物流系统,得有清晰的思路。偶尔也会有一些开放问题,比如你觉得Agent未来会往哪个方向走,多模态或者行业专用Agent算不算趋势,还有作为Java开发者,转型做Agent开发的优势和挑战是什么,这些问题能看出你有没有自己的思考,不是单纯跟风入行。总的来说,Agent面试不怎么考死记硬背的东西,更看重你对技术的理解和实际动手能力,尤其是怎么把AI和业务结合起来,解决真实问题。
查看13道真题和解析
点赞 评论 收藏
分享
评论
点赞
6
分享

创作者周榜

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