MST
星途 面试题库

面试题:C++ 智能指针的类型及基础应用

请简述C++中智能指针的三种类型(std::unique_ptr、std::shared_ptr、std::weak_ptr)各自的特点,并举例说明在何种场景下适合使用std::unique_ptr和std::shared_ptr。
41.9万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

std::unique_ptr特点

  1. 独占所有权std::unique_ptr 拥有对对象的唯一所有权,同一时刻只能有一个 std::unique_ptr 指向给定对象。当 std::unique_ptr 被销毁(例如离开其作用域)时,它所指向的对象也会被自动销毁。
  2. 不能复制:不支持拷贝构造函数和拷贝赋值运算符,只能通过移动语义来转移所有权。这使得 std::unique_ptr 非常适合用于管理动态分配的资源,避免资源泄漏。
  3. 性能高效:由于其简单的所有权模型,std::unique_ptr 通常具有非常小的运行时开销,接近于普通指针。

std::shared_ptr特点

  1. 共享所有权std::shared_ptr 允许多个 std::shared_ptr 指向同一个对象,通过引用计数来管理对象的生命周期。当最后一个指向对象的 std::shared_ptr 被销毁时,对象才会被释放。
  2. 支持复制:支持拷贝构造函数和拷贝赋值运算符,每次复制都会增加引用计数。这使得 std::shared_ptr 非常适合用于需要在多个地方共享资源的场景。
  3. 线程安全:引用计数的递增和递减是线程安全的,因此 std::shared_ptr 可以在多线程环境中安全使用,但对象的访问和修改可能仍需要额外的同步机制。

std::weak_ptr特点

  1. 弱引用std::weak_ptr 不拥有对象的所有权,它是对 std::shared_ptr 所管理对象的一个弱引用。std::weak_ptr 不会影响对象的引用计数,即不会阻止对象被销毁。
  2. 解决循环引用:常用于解决 std::shared_ptr 之间可能出现的循环引用问题。通过使用 std::weak_ptr 打破循环引用,确保对象在不再被需要时能够正确释放。
  3. 过期检查:可以通过 lock() 成员函数尝试获取一个 std::shared_ptr,如果对象已被销毁(即引用计数为 0),lock() 将返回一个空的 std::shared_ptr

std::unique_ptr适用场景举例

  1. 资源独占场景:当一个资源只应由一个对象管理,例如一个文件句柄。假设我们有一个 FileHandler 类用于管理文件操作,在这种情况下使用 std::unique_ptr 是合适的。
#include <iostream>
#include <memory>
#include <fstream>

class FileHandler {
public:
    FileHandler(const std::string& filename) : file_(std::make_unique<std::ofstream>(filename)) {
        if (!file_->is_open()) {
            throw std::runtime_error("Failed to open file");
        }
    }

    ~FileHandler() = default;

    void write(const std::string& data) {
        if (file_->is_open()) {
            *file_ << data;
        }
    }

private:
    std::unique_ptr<std::ofstream> file_;
};

在上述代码中,FileHandler 类使用 std::unique_ptr<std::ofstream> 来管理文件对象。每个 FileHandler 实例独占文件的所有权,当 FileHandler 对象被销毁时,文件会自动关闭。

std::shared_ptr适用场景举例

  1. 多对象共享资源场景:假设有一个图形渲染系统,其中有多个 Shape 对象可能共享一个 Texture 资源。
#include <iostream>
#include <memory>
#include <string>

class Texture {
public:
    Texture(const std::string& name) : name_(name) {
        std::cout << "Texture " << name_ << " created" << std::endl;
    }

    ~Texture() {
        std::cout << "Texture " << name_ << " destroyed" << std::endl;
    }

    const std::string& getName() const {
        return name_;
    }

private:
    std::string name_;
};

class Shape {
public:
    Shape(const std::string& type, std::shared_ptr<Texture> texture) : type_(type), texture_(texture) {
        std::cout << "Shape " << type_ << " created with texture " << texture_->getName() << std::endl;
    }

    ~Shape() {
        std::cout << "Shape " << type_ << " destroyed" << std::endl;
    }

private:
    std::string type_;
    std::shared_ptr<Texture> texture_;
};

在上述代码中,多个 Shape 对象可以共享同一个 Texture 对象,Texture 对象的生命周期由 std::shared_ptr 自动管理,只有当所有指向它的 std::shared_ptr 都被销毁时,Texture 才会被释放。