MST

星途 面试题库

面试题:C++ 智能指针基础与内存安全性场景分析

在C++中,智能指针是提升内存管理安全性的重要工具。请阐述std::unique_ptr、std::shared_ptr和std::weak_ptr的主要区别,并举例说明在一个简单的类继承体系中,如何正确使用std::unique_ptr来管理派生类对象,以确保内存安全,避免悬空指针和内存泄漏。
42.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

std::unique_ptr、std::shared_ptr 和 std::weak_ptr 的主要区别

  1. 所有权
    • std::unique_ptr:拥有对对象的唯一所有权。一旦 std::unique_ptr 被销毁,它所指向的对象也会被销毁。它不能被复制,但可以转移所有权。
    • std::shared_ptr:允许多个指针共享对一个对象的所有权。通过引用计数机制来管理对象的生命周期,当引用计数为 0 时,对象被自动销毁。
    • std::weak_ptr:不拥有对象的所有权,它是对 std::shared_ptr 所管理对象的一种弱引用。它不会增加对象的引用计数,主要用于解决 std::shared_ptr 中的循环引用问题,避免内存泄漏。
  2. 性能
    • std::unique_ptr:由于其简单的所有权模型,通常具有最小的运行时开销,性能较好。
    • std::shared_ptr:由于需要维护引用计数,开销相对较大,尤其是在多线程环境下,引用计数的更新需要额外的同步操作。
    • std::weak_ptr:开销主要在于创建和销毁时与 std::shared_ptr 的交互,本身不影响对象的生命周期管理。
  3. 应用场景
    • std::unique_ptr:适用于对象只应由一个所有者管理的场景,例如函数内部局部对象的管理,或资源的独占式管理。
    • std::shared_ptr:适用于对象需要被多个部分共享的场景,如在多个模块间传递对象的所有权。
    • std::weak_ptr:通常与 std::shared_ptr 一起使用,用于打破循环引用,或在对象可能被释放的情况下安全地访问对象。

使用 std::unique_ptr 在类继承体系中管理派生类对象

#include <iostream>
#include <memory>

class Base {
public:
    virtual ~Base() {
        std::cout << "Base destructor" << std::endl;
    }
};

class Derived : public Base {
public:
    ~Derived() {
        std::cout << "Derived destructor" << std::endl;
    }
};

void testUniquePtr() {
    std::unique_ptr<Base> ptr = std::make_unique<Derived>();
    // 这里可以通过ptr访问Base类和Derived类的成员函数
    // 当ptr离开作用域时,Derived对象会被自动销毁
}

int main() {
    testUniquePtr();
    return 0;
}

在上述代码中:

  1. 创建对象:使用 std::make_unique<Derived>() 创建一个 Derived 对象,并将其所有权转移给 std::unique_ptr<Base> 类型的 ptrstd::make_unique 是 C++14 引入的函数,用于更安全和高效地创建 std::unique_ptr
  2. 内存管理:当 ptr 离开其作用域(testUniquePtr 函数结束)时,Derived 对象会被自动销毁,从而确保了内存安全,避免了悬空指针和内存泄漏。由于 Base 类有虚析构函数,Derived 类的析构函数会被正确调用。