网易互娱-游戏研发-C++ 一面

1. emplace_back 和 push_back 之间的区别是什么?

push_back 接受一个已经构造好的对象。如果传入的是构造函数的参数,它会先调用构造函数生成一个临时对象,然后再通过拷贝构造或移动构造将该对象放入容器,最后销毁临时对象。emplace_back 利用 C++11 的完美转发(Perfect Forwarding)和可变参数模板,直接在容器的底层内存空间中原地构造对象,省去了创建和销毁临时对象的步骤。

2. emplace_back 是否比 push_back 更高效?

不一定总是更高效。当传入的是构造函数的参数时,emplace_back 省去了临时对象的拷贝/移动,确实更高效。当传入的是已经存在的局部对象时,两者的底层行为完全一致,都会调用移动构造函数或拷贝构造函数,性能没有差异。此外,滥用 emplace_back 可能会因为隐式类型转换而绕过显式的构造函数声明。

3. make_shared 的底层原理是什么?

传统的 std::shared_ptr<T>(new T()) 需要进行两次内存分配:一次是为对象 T 分配堆内存,另一次是为智能指针的控制块(用于存放引用计数等信息)分配内存。std::make_shared<T>() 的底层原理是:只进行一次内存分配,分配一块足够大的连续内存,将对象 T 和控制块放在一起原地构造。这样提升了内存分配效率,避免了内存碎片,并在抛出异常时更加安全。

4. shared_ptr 有什么致命缺陷?如何解决?

致命缺陷是循环引用(Circular Reference),会导致两者的引用计数永远降不到 0,发生内存泄漏。解决办法是使用 std::weak_ptr。weak_ptr 不会增加控制块的强引用计数,如果需要访问对象,可以通过 lock() 提升为临时的 shared_ptr。

#include <memory>

struct Node {
    std::weak_ptr<Node> next; // 使用 weak_ptr 打破循环
    ~Node() {}
};

void test() {
    auto a = std::make_shared<Node>();
    auto b = std::make_shared<Node>();
    a->next = b;
    b->next = a;
} // 正常析构,不泄漏

5. 平时项目里的 C++ 主要是用到哪个版本?

主要使用 C++11 和 C++14。重点使用了 C++11 的智能指针(管理内存)、右值引用(优化移动语义)、并发库(多线程同步)以及 auto 类型推导;使用 C++14 的泛型 Lambda 与 std::make_unique 提升安全性与开发效率。

6. std::move 会真实地“移动”内存吗?它的底层做了什么?

不会。std::move 在运行时不产生任何汇编代码,不移动任何内存。它的底层逻辑仅仅是一个编译期的强制类型转换,将左值无条件转化为右值引用。真正的移动操作是由对象的移动构造函数或移动赋值运算符完成的。

// std::move 底层核心等价于:
template<typename T>
typename std::remove_reference<T>::type&& move(T&& arg) noexcept {
    return static_cast<typename std::remove_reference<T>::type&&>(arg);
}

7. 解释一段 C++20 的代码思想

面试题通常会给出如下代码段,要求解释:

#include <iostream>
#include <ranges>
#include <vector>

int main() {
    std::vector<int> nums = {1, 2, 3, 4, 5, 6};
    auto result = nums | std::views::filter([](int n){ return n % 2 == 0; })
                       | std::views::transform([](int n){ return n * n; });
    for (int n : result) std::cout << n << " ";
}

这段代码使用了 C++20 的 Ranges 库。它利用管道符 | 将多个操作串联起来,体现了函数式编程思想。核心机制是延迟计算(Lazy Evaluation):filter 和 transform 不会立即生成中间容器,而是在最终遍历 result 时才求值,极大减少了内存开销并提升了代码可读性。

8. TCP 三次握手为什么不

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

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

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

全部评论
写的真的多,有后续吗
点赞 回复 分享
发布于 03-04 19:00 北京

相关推荐

03-06 17:03
北京大学 C++
1.C++11&nbsp;的新特性有哪些1.1说下智能指针1.1.1shared_ptr&nbsp;它是线程安全的吗1.2nullptr&nbsp;有什么作用,以前有&nbsp;NULL,为什么要加一个&nbsp;nullptr2.const&nbsp;和&nbsp;static&nbsp;的作用2.1还有哪些其他作用,如修饰函数,修饰类里面的函数、类里面的变量。2.2声明类的时候加一个&nbsp;const,能调用它里面的成员函数吗3.C++&nbsp;有哪些类型转换,如&nbsp;static_cast&nbsp;之类的3.1reinterpret_cast&nbsp;的作用是什么3.2了解过&nbsp;dynamic_cast&nbsp;吗4.C++&nbsp;有哪些&nbsp;STL&nbsp;容器4.1vector&nbsp;和&nbsp;list&nbsp;有什么区别5.C++&nbsp;一些网络你知道吗,epoll&nbsp;你用过吗6.你用&nbsp;Linux&nbsp;多吗,看一些网络、磁盘&nbsp;IO、CPU&nbsp;性能的工具了解吗6.1那网络流量,一个节点到另一个节点的占比的工具用过吗7.进程和线程有什么区别7.1进程之间通信有哪些方式7.1.1信号量了解吗7.2线程之间有哪些通信方式7.2.1锁了解过吗,条件变量了解过吗8.TCP&nbsp;和&nbsp;UDP&nbsp;的区别8.1TCP&nbsp;和&nbsp;UDP&nbsp;都发送若干个网络包,都能确保完整收到这些包吗,收到的顺序对不对9.git&nbsp;用的是命令还是&nbsp;GUI9.1写了一些代码还没有存进去,但是另一个人提了一个版本要合进来,该怎么操作9.2git&nbsp;stash&nbsp;有什么作用10.MySQL&nbsp;的事务隔离级别有哪些11.怎么知道哪些线程占用的&nbsp;CPU&nbsp;比较多12.用过哪些&nbsp;AI&nbsp;编程工具12.1改变量的名字的时候用的惯吗13.LeetCode128&nbsp;最长连续序列吓哭了,沉浸式拷打,自己掌握的还是太薄弱了,面试官人好实力又强,我菜菜😭😭😭
查看30道真题和解析
点赞 评论 收藏
分享
评论
1
10
分享

创作者周榜

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