MST

星途 面试题库

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

请简述C++中std::unique_ptr、std::shared_ptr和std::weak_ptr三种智能指针的特点,并举例说明它们各自适合的应用场景。
26.0万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

std::unique_ptr

  • 特点
    • 独占式智能指针,同一时间只有一个std::unique_ptr能指向一个对象。
    • std::unique_ptr被销毁时,它所指向的对象也会被自动销毁。
    • 不能进行拷贝构造和拷贝赋值,但可以进行移动构造和移动赋值。
  • 应用场景
    • 资源管理,如文件句柄、网络连接等,只需要一个对象管理资源。
    • 示例:
#include <iostream>
#include <memory>

class Resource {
public:
    Resource() { std::cout << "Resource created" << std::endl; }
    ~Resource() { std::cout << "Resource destroyed" << std::endl; }
};

int main() {
    std::unique_ptr<Resource> res1 = std::make_unique<Resource>();
    // std::unique_ptr<Resource> res2 = res1;  // 错误,不能拷贝
    std::unique_ptr<Resource> res2 = std::move(res1);  // 移动所有权
    return 0;
}

std::shared_ptr

  • 特点
    • 共享式智能指针,允许多个std::shared_ptr指向同一个对象。
    • 通过引用计数来管理对象的生命周期,当引用计数为0时,对象自动销毁。
    • 支持拷贝构造和拷贝赋值。
  • 应用场景
    • 多个对象需要共享资源,如共享数据缓存。
    • 示例:
#include <iostream>
#include <memory>

class Resource {
public:
    Resource() { std::cout << "Resource created" << std::endl; }
    ~Resource() { std::cout << "Resource destroyed" << std::endl; }
};

int main() {
    std::shared_ptr<Resource> res1 = std::make_shared<Resource>();
    std::shared_ptr<Resource> res2 = res1;  // 拷贝,引用计数增加
    std::cout << "res1 use count: " << res1.use_count() << std::endl;
    std::cout << "res2 use count: " << res2.use_count() << std::endl;
    return 0;
}

std::weak_ptr

  • 特点
    • 弱引用智能指针,指向由std::shared_ptr管理的对象,但不增加对象的引用计数。
    • 可以用来解决std::shared_ptr的循环引用问题。
    • 它需要通过lock()方法来获取一个有效的std::shared_ptr
  • 应用场景
    • 解决循环引用问题,如双向链表。
    • 示例:
#include <iostream>
#include <memory>

class B;

class A {
public:
    std::weak_ptr<B> weak_b;
    ~A() { std::cout << "A destroyed" << std::endl; }
};

class B {
public:
    std::shared_ptr<A> shared_a;
    ~B() { std::cout << "B destroyed" << std::endl; }
};

int main() {
    std::shared_ptr<A> a = std::make_shared<A>();
    std::shared_ptr<B> b = std::make_shared<B>();
    a->weak_b = b;
    b->shared_a = a;
    return 0;
}

在这个例子中,如果B中使用std::weak_ptr指向A,就能避免循环引用导致的内存泄漏。