如何通过C++面试:高级别热门问题

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

如何通过C++面试:高级别热门问题

\n\n

中高级C++开发人员的面试不仅仅是检查语法。面试官希望看到对语言内部机制的深入理解,以及处理内存、模板和多线程的能力。在本文中,我们整理了C++高级别面试中最常见和最复杂的问题。每个问题都附有解释和代码示例。

\n\n

1. 智能指针与RAII

\n\n

关于智能指针的问题是经典问题。期望您不仅能说出std::unique_ptr、std::shared_ptr和std::weak_ptr,还能解释它们的内部机制以及何时使用哪一个。

\n\n

典型问题:unique_ptr和shared_ptr有什么区别?shared_ptr中的引用计数是如何工作的?为什么需要weak_ptr?

\n\n

答案:std::unique_ptr是资源的独占所有权。它不能被复制,只能被移动(移动语义)。std::shared_ptr使用引用计数来实现共享所有权。当计数降至零时,对象被删除。std::weak_ptr是一个“观察者”,它不会增加引用计数。它用于防止循环依赖(例如,在图或树中)。

\n\n
#include <memory>\n#include <iostream>\n\nstruct Resource {\n    Resource() { std::cout << "Resource acquired\\n"; }\n    ~Resource() { std::cout << "Resource released\\n"; }\n};\n\nint main() {\n    // unique_ptr\n    std::unique_ptr<Resource> ptr1 = std::make_unique<Resource>();\n    // std::unique_ptr<Resource> ptr2 = ptr1; // 编译错误 - 禁止复制\n    std::unique_ptr<Resource> ptr2 = std::move(ptr1); // 允许移动\n\n    // shared_ptr\n    std::shared_ptr<Resource> sptr1 = std::make_shared<Resource>();\n    std::shared_ptr<Resource> sptr2 = sptr1; // 允许复制,计数 = 2\n\n    // weak_ptr\n    std::weak_ptr<Resource> wptr = sptr1; // 计数不增加\n    if (auto locked = wptr.lock()) {\n        std::cout << "Resource is still alive\\n";\n    }\n\n    return 0;\n}
\n\n

附加问题:如何实现自己的SharedPtr?这里重要的是提到RAII(资源获取即初始化)——一种在构造函数中获取资源、在析构函数中释放资源的原则。

\n\n

2. 虚析构函数与虚函数表(vtable)

\n\n

这个问题考察对多态性和C++中虚函数机制的理解。

\n\n

典型问题:为什么带有虚函数的基类必须要有虚析构函数?vtable是如何工作的?

\n\n

答案:如果基类的析构函数不是虚函数,那么当通过基类指针删除派生类对象时,只会调用基类的析构函数。这将导致派生类分配的资源泄漏。

\n\n

每个至少有一个虚函数的类都包含一个静态表(vtable)。表中存储了指向虚函数实现的指针。该类的每个对象都有一个隐藏指针(vptr),指向其类的vtable。虚函数的调用通过双重间接进行:对象 → vptr → vtable → 函数。与普通调用相比,这增加了一些开销。

\n\n
#include <iostream>\n\nclass Base {\npublic:\n    virtual void show() { std::cout << "Base\\n"; }\n    virtual ~Base() = default; // 虚析构函数\n};\n\nclass Derived : public Base {\npublic:\n    void show() override { std::cout << "Deriv                

博客

书籍推荐