• 【面试系列】C++ 高频面试题


    欢迎来到我的博客,很高兴能够在这里和您见面!欢迎订阅相关专栏:

    ⭐️ 全网最全IT互联网公司面试宝典:收集整理全网各大IT互联网公司技术、项目、HR面试真题.
    ⭐️ AIGC时代的创新与未来:详细讲解AIGC的概念、核心技术、应用领域等内容。
    ⭐️ 全流程数据技术实战指南:全面讲解从数据采集到数据可视化的整个过程,掌握构建现代化数据平台和数据仓库的核心技术和方法。

    文章目录

    C++ 初级面试题及其详细解答

    1. 解释 C++ 中的基本数据类型。

    解答
    C++ 提供了几种基本数据类型,包括:

    • int:整型,用于存储整数。
    • floatdouble:浮点型,用于存储小数。
    • char:字符型,用于存储单个字符。
    • bool:布尔型,用于存储 truefalse 值。
    • void:无类型,通常用于函数返回类型。

    示例:

    int a = 10;
    float b = 3.14;
    char c = 'A';
    bool d = true;
    

    2. 如何在 C++ 中定义和使用函数?

    解答
    在 C++ 中定义函数需要指定返回类型、函数名和参数列表。使用函数时通过函数名和参数进行调用。

    示例:

    #include 
    using namespace std;
    
    int add(int x, int y) {
        return x + y;
    }
    
    int main() {
        int result = add(3, 4);
        cout << "Result: " << result << endl;
        return 0;
    }
    

    3. 解释 C++ 中的引用和指针。

    解答

    • 引用:是已有变量的别名,定义时必须初始化,不能更改引用目标。
    • 指针:是存储变量地址的变量,可以在初始化后修改指向的地址。

    示例:

    int a = 5;
    int& ref = a;  // 引用
    int* ptr = &a; // 指针
    
    ref = 10; // 修改 a 的值
    *ptr = 15; // 修改 a 的值
    

    4. 什么是类和对象?如何定义和使用?

    解答

    • :是定义对象的蓝图,包含属性和方法。
    • 对象:是类的实例,通过类创建。

    示例:

    class MyClass {
    public:
        int x;
        void display() {
            cout << "Value: " << x << endl;
        }
    };
    
    int main() {
        MyClass obj;
        obj.x = 10;
        obj.display();
        return 0;
    }
    

    5. 解释构造函数和析构函数。

    解答

    • 构造函数:是类的特殊函数,用于初始化对象。名称与类名相同,无返回类型。
    • 析构函数:在对象销毁时调用,用于清理资源。名称与类名相同,前加 ~ 符号,无返回类型。

    示例:

    class MyClass {
    public:
        MyClass() { cout << "Constructor called" << endl; }
        ~MyClass() { cout << "Destructor called" << endl; }
    };
    
    int main() {
        MyClass obj;
        return 0;
    }
    

    6. 如何在 C++ 中实现函数重载?

    解答
    函数重载是指在同一个作用域内定义多个函数,这些函数具有相同的名称但参数列表不同。

    示例:

    #include 
    using namespace std;
    
    int add(int a, int b) {
        return a + b;
    }
    
    double add(double a, double b) {
        return a + b;
    }
    
    int main() {
        cout << "Int add: " << add(3, 4) << endl;
        cout << "Double add: " << add(3.5, 4.5) << endl;
        return 0;
    }
    

    7. 解释 C++ 中的继承。

    解答
    继承是面向对象编程的特性,允许一个类从另一个类派生,继承基类的属性和方法。使用 : 和访问控制符(public, protected, private)实现继承。

    示例:

    class Base {
    public:
        void display() {
            cout << "Base class display" << endl;
        }
    };
    
    class Derived : public Base {
    public:
        void show() {
            cout << "Derived class show" << endl;
        }
    };
    
    int main() {
        Derived obj;
        obj.display();
        obj.show();
        return 0;
    }
    

    8. 解释 C++ 中的虚函数和纯虚函数。

    解答

    • 虚函数:使用 virtual 关键字声明,可以在派生类中重写,实现多态性。
    • 纯虚函数:使用 = 0 声明,必须在派生类中实现,所在类为抽象类,不能实例化。

    示例:

    class Base {
    public:
        virtual void display() {
            cout << "Base display" << endl;
        }
    };
    
    class Derived : public Base {
    public:
        void display() override {
            cout << "Derived display" << endl;
        }
    };
    
    int main() {
        Base* ptr = new Derived();
        ptr->display();  // 输出:Derived display
        delete ptr;
        return 0;
    }
    

    9. 解释 C++ 中的模板。

    解答
    模板是泛型编程的基础,允许定义函数或类时使用类型参数,从而在使用时指定具体类型。分为函数模板和类模板。

    示例:

    template <typename T>
    T add(T a, T b) {
        return a + b;
    }
    
    int main() {
        cout << "Int add: " << add(3, 4) << endl;
        cout << "Double add: " << add(3.5, 4.5) << endl;
        return 0;
    }
    

    10. 如何在 C++ 中处理异常?

    解答
    使用 trycatchthrow 关键字处理异常。try 块中放置可能抛出异常的代码,catch 块处理异常,throw 抛出异常。

    示例:

    #include 
    using namespace std;
    
    int divide(int a, int b) {
        if (b == 0) {
            throw runtime_error("Division by zero");
        }
        return a / b;
    }
    
    int main() {
        try {
            cout << divide(10, 0) << endl;
        } catch (const runtime_error& e) {
            cout << "Error: " << e.what() << endl;
        }
        return 0;
    }
    

    C++ 中级面试题及其详细解答

    1. 解释 C++ 中的深拷贝与浅拷贝的区别。

    解答

    • 浅拷贝:拷贝对象的所有成员,包括指针,但不会拷贝指针所指向的内容,导致多个对象共享同一块内存。
    • 深拷贝:不仅拷贝对象的所有成员,还会拷贝指针所指向的内容,确保每个对象都有独立的内存。

    示例:

    class MyClass {
    public:
        int* data;
        MyClass(int value) {
            data = new int(value);
        }
        // 深拷贝构造函数
        MyClass(const MyClass& other) {
            data = new int(*other.data);
        }
        ~MyClass() {
            delete data;
        }
    };
    

    2. 解释 C++ 中的智能指针及其类型。

    解答
    C++11 引入了智能指针,自动管理动态内存,防止内存泄漏。常见类型包括:

    • std::unique_ptr:独占所有权,一个时间点只有一个智能指针指向对象。
    • std::shared_ptr:共享所有权,多个智能指针可以指向同一对象,使用引用计数管理。
    • std::weak_ptr:弱引用,不增加引用计数,避免循环引用。

    示例:

    #include 
    
    std::unique_ptr<int> p1(new int(5));
    std::shared_ptr<int> p2 = std::make_shared<int>(10);
    std::weak_ptr<int> p3 = p2;
    

    3. 如何在 C++ 中实现一个简单的 RAII 类?

    解答
    RAII(资源获取即初始化)是一种管理资源的惯用方法,通过对象的生命周期管理资源。实现一个简单的 RAII 类,确保资源在构造时获取,在析构时释放。

    示例:

    class RAII {
    public:
        RAII() {
            resource = new int(5);  // 获取资源
        }
        ~RAII() {
            delete resource;  // 释放资源
        }
    private:
        int* resource;
    };
    
    int main() {
        RAII obj;
        // 资源在作用域结束时自动释放
        return 0;
    }
    

    4. 解释 C++ 中的多态性及其实现方式。

    解答
    多态性允许通过基类指针或引用调用派生类的方法。实现方式包括:

    • 编译时多态:通过函数重载和模板实现。
    • 运行时多态:通过虚函数实现。

    示例:

    class Base {
    public:
        virtual void show() {
            cout << "Base show" << endl;
        }
    };
    
    class Derived : public Base {
    public:
        void show() override {
            cout << "Derived show" << endl;
        }
    };
    
    int main() {
        Base* ptr = new Derived();
        ptr->show();  // 输出:Derived show
        delete ptr;
    }
    

    5. 什么是拷贝构造函数和赋值运算符重载?为什么需要它们?

    解答

    • 拷贝构造函数:用于创建对象的副本,防止默认浅拷贝导致资源冲突。语法:ClassName(const ClassName& other);
    • 赋值运算符重载:用于赋值操作,防止默认浅拷贝导致资源冲突。语法:ClassName& operator=(const ClassName& other);

    示例:

    class MyClass {
    public:
        int* data;
        MyClass(int value) {
            data = new int(value);
        }
        // 拷贝构造函数
        MyClass(const MyClass& other) {
            data = new int(*other.data);
        }
        // 赋值运算符重载
        MyClass& operator=(const MyClass& other) {
            if (this != &other) {
                delete data;
                data = new int(*other.data);
            }
            return *this;
        }
        ~MyClass() {
            delete data;
        }
    };
    

    6. 解释 C++ 中的虚函数表(V-Table)。

    解答
    虚函数表是编译器为支持多态性生成的结构。它包含类的虚函数指针。每个包含虚函数的类实例都有一个隐藏的指针指向对应的虚函数表。调用虚函数时,通过虚函数表找到实际调用的函数地址。

    示例:

    class Base {
    public:
        virtual void show() {
            cout << "Base show" << endl;
        }
    };
    
    class Derived : public Base {
    public:
        void show() override {
            cout << "Derived show" << endl;
        }
    };
    
    int main() {
        Base* ptr = new Derived();
        ptr->show();  // 通过 V-Table 调用 Derived::show
        delete ptr;
    }
    

    7. 解释 C++ 中的内联函数及其优缺点。

    解答
    内联函数通过 inline 关键字声明,提示编译器将函数体展开到调用处,减少函数调用开销。优点包括减少函数调用开销,提高执行效率。缺点是可能增加代码大小,导致指令缓存效率降低。

    示例:

    inline int add(int a, int b) {
        return a + b;
    }
    
    int main() {
        int result = add(3, 4);  // 内联展开,减少调用开销
        return 0;
    }
    

    8. 解释 C++ 中的命名空间及其用途。

    解答
    命名空间用于组织代码,避免命名冲突。使用 namespace 关键字定义,通过作用域解析运算符 :: 访问命名空间中的成员。常用于大型项目和库中。

    示例:

    namespace MyNamespace {
        int value = 10;
        void show() {
            cout << "Value: " << value << endl;
        }
    }
    
    int main() {
        MyNamespace::show();  // 访问 MyNamespace 中的成员
        return 0;
    }
    

    9. 解释 C++ 中的虚继承及其用途。

    解答
    虚继承用于解决多重继承中的菱形继承问题,防止基类的多份拷贝。使用 virtual 关键字声明虚继承。这样,派生类只包含一份基类的成员。

    示例:

    class Base {
    public:
        int value;
    };
    
    class Derived1 : virtual public Base {};
    class Derived2 : virtual public Base {};
    
    class Final : public Derived1, public Derived2 {
    public:
        void show() {
            value = 10;  // 没有二义性
            cout << "Value: " << value << endl;
        }
    };
    
    int main() {
        Final obj;
        obj.show();
        return 0;
    }
    

    10. 解释 C++11 引入的 nullptr 和其优势。

    解答
    nullptr 是 C++11 引入的空指针常量,用于替代 NULL0,解决了它们与整数混淆的问题。nullptrstd::nullptr_t 类型,能更明确地表示指针为空,提高代码可读性和类型安全性。

    示例:

    void func(int x) {
        cout << "Integer: " << x << endl;
    }
    
    void func(int* ptr) {
        cout << "Pointer" << endl;
    }
    
    int main() {
        func(0);        // 调用 func(int)
        func(nullptr);  // 调用 func(int*)
        return 0;
    }
    

    C++ 高级面试题及其详细解答

    1. 解释 C++ 中的内存模型和内存管理。

    解答
    C++ 中的内存模型包括堆、栈、自由存储区和全局/静态区:

    • :局部变量和函数调用信息,自动管理。
    • :动态分配内存,需要手动管理(newdelete)。
    • 自由存储区mallocfree 管理的内存。
    • 全局/静态区:存储全局变量和静态变量,在程序结束时释放。

    内存管理包括防止内存泄漏、双重释放、无效指针等问题。智能指针(如 std::unique_ptrstd::shared_ptr)有助于自动管理内存,减少内存泄漏风险。

    2. 解释 C++11 中的移动语义和 std::move 的作用。

    解答
    移动语义通过引入右值引用(T&&)和移动构造函数、移动赋值运算符,优化资源管理,避免不必要的拷贝。std::move 用于将左值强制转换为右值引用,允许对象资源的转移,而不是复制。

    示例:

    #include 
    
    class MyClass {
    public:
        MyClass() : data(new int[100]) {}
        ~MyClass() { delete[] data; }
    
        // 移动构造函数
        MyClass(MyClass&& other) noexcept : data(other.data) {
            other.data = nullptr;
        }
    
        // 移动赋值运算符
        MyClass& operator=(MyClass&& other) noexcept {
            if (this != &other) {
                delete[] data;
                data = other.data;
                other.data = nullptr;
            }
            return *this;
        }
    
    private:
        int* data;
    };
    
    int main() {
        MyClass obj1;
        MyClass obj2 = std::move(obj1);  // 使用移动构造函数
        return 0;
    }
    

    3. 解释 C++ 中的线程与线程同步机制。

    解答
    C++11 引入了线程支持,提供了 std::thread 进行多线程编程。线程同步机制包括:

    • 互斥锁(std::mutex:保护共享数据,防止数据竞争。
    • 条件变量(std::condition_variable:实现线程间的等待和通知。
    • 读写锁(std::shared_mutex:允许多个线程并发读取,独占写入。

    示例:

    #include 
    #include 
    #include 
    
    std::mutex mtx;
    
    void print(int i) {
        std::lock_guard<std::mutex> lock(mtx);
        std::cout << "Thread " << i << std::endl;
    }
    
    int main() {
        std::thread t1(print, 1);
        std::thread t2(print, 2);
        t1.join();
        t2.join();
        return 0;
    }
    

    4. 如何实现一个线程安全的单例模式?

    解答
    使用双重检查锁定实现线程安全的单例模式。确保在多线程环境下只有一个实例被创建。

    示例:

    #include 
    
    class Singleton {
    public:
        static Singleton* getInstance() {
            if (instance == nullptr) {
                std::lock_guard<std::mutex> lock(mtx);
                if (instance == nullptr) {
                    instance = new Singleton();
                }
            }
            return instance;
        }
    
    private:
        Singleton() {}
        static Singleton* instance;
        static std::mutex mtx;
    };
    
    Singleton* Singleton::instance = nullptr;
    std::mutex Singleton::mtx;
    

    5. 解释 C++ 中的 constexpr 和其优势。

    解答
    constexpr 是 C++11 引入的关键字,用于指定常量表达式,允许在编译时计算结果。优势包括:

    • 编译时计算:提高程序效率,减少运行时开销。
    • 类型安全:通过编译时检查,提高代码安全性和可靠性。
    • 优化机会:允许编译器进行更好的优化。

    示例:

    constexpr int square(int x) {
        return x * x;
    }
    
    int main() {
        constexpr int result = square(5);  // 编译时计算
        return 0;
    }
    

    6. 解释 C++ 中的协程及其应用。

    解答
    协程是 C++20 引入的特性,允许函数在执行过程中暂停和恢复,实现异步编程。通过 co_awaitco_yieldco_return 关键字使用协程。协程的应用包括事件驱动编程、异步 IO 和生成器等。

    示例:

    #include 
    #include 
    
    struct Coroutine {
        struct promise_type {
            Coroutine get_return_object() { return {}; }
            std::suspend_always initial_suspend() { return {}; }
            std::suspend_always final_suspend() noexcept { return {}; }
            void return_void() {}
            void unhandled_exception() { std::terminate(); }
        };
    };
    
    Coroutine myCoroutine() {
        std::cout << "Hello ";
        co_await std::suspend_always{};
        std::cout << "World!" << std::endl;
    }
    
    int main() {
        auto coro = myCoroutine();
        coro.resume();
        return 0;
    }
    

    7. 解释 C++ 中的 CRTP(Curiously Recurring Template Pattern)。

    解答
    CRTP 是一种模板编程技术,基类以派生类作为模板参数,实现静态多态性。CRTP 的优势包括编译时多态性、性能优化和代码重用。常用于实现静态接口和 CRTP 组合。

    示例:

    template <typename Derived>
    class Base {
    public:
        void interface() {
            static_cast<Derived*>(this)->implementation();
        }
    
        static void staticInterface() {
            Derived::staticImplementation();
        }
    };
    
    class Derived : public Base<Derived> {
    public:
        void implementation() {
            std::cout << "Derived implementation" << std::endl;
        }
    
        static void staticImplementation() {
            std::cout << "Derived static implementation" << std::endl;
        }
    };
    
    int main() {
        Derived d;
        d.interface();  // 输出:Derived implementation
        Derived::staticInterface();  // 输出:Derived static implementation
        return 0;
    }
    

    8. 如何在 C++ 中实现 RAII(资源获取即初始化)?

    解答
    RAII 是 C++ 管理资源的惯用方法,通过对象的生命周期管理资源。常见的 RAII 包括 std::lock_guardstd::unique_ptr。RAII 类在构造时获取资源,在析构时释放资源。

    示例:

    #include 
    
    class LockGuard {
    public:
        LockGuard(std::mutex& m) : mtx(m) {
            mtx.lock();
        }
        ~LockGuard() {
            mtx.unlock();
        }
    private:
        std::mutex& mtx;
    };
    
    std::mutex mtx;
    
    int main() {
        {
            LockGuard lock(mtx);
            // 临界区
        }  // 自动释放锁
        return 0;
    }
    

    9. 解释 C++ 中的 SFINAE(Substitution Failure Is Not An Error)。

    解答
    SFINAE 是一种模板编程技术,当模板参数替换失败时,不会产生编译错误,而是选择其他重载。SFINAE 用于实现模板的条件编译、类型推导和静态多态性。常用工具包括 std::enable_if 和类型特征。

    示例:

    #include 
    #include 
    
    template <typename T>
    typename std::enable_if<std::is_integral<T>::value, void>::type
    print(T value) {
        std::cout << "Integral: " << value << std::endl;
    }
    
    template <typename T>
    typename std::enable_if<std::is_floating_point<T>::value, void>::type
    print(T value) {
        std::cout << "Floating point: " << value << std::endl;
    }
    
    int main() {
        print(42);         // 输出:Integral: 42
        print(3.14);       // 输出:Floating point: 3.14
        return 0;
    }
    

    10. 解释 C++ 中的表达式模板及其用途。

    解答
    表达式模板是一种模板编程技术,通过构建表达式树,在编译时优化计算。常用于高性能计算库(如 EigenBoost),避免不必要的临时对象和拷贝,提高计算效率。

    示例:

    template <typename L, typename R>
    class Add {
    public:
        Add(const L& l, const R& r) : lhs(l), rhs(r) {}
    
        auto operator[](size_t i) const {
            return lhs[i] + rhs[i];
        }
    
    private:
        const L& lhs
    

    💗💗💗 如果觉得这篇文对您有帮助,请给个点赞、关注、收藏吧,谢谢!💗💗💗

  • 相关阅读:
    两化融合管理体系所有需要上传平台内容集合
    从零开始学React--环境搭建
    微服务架构 | 架构演进
    pip安装numpy显示没有pip模块怎么办
    山东大学人工智能导论实验四 利用神经网络分类红色和蓝色的花
    PMP课程笔记:第13章 项目相关方管理
    lightdb Oracle模式下to_char支持格式‘HH24MiSS‘
    兄弟DCP-7080激光打印机硒鼓清零方法
    Redis面试---缓存问题
    VS新功能:智能添加函数标记
  • 原文地址:https://blog.csdn.net/u010225915/article/details/139955645