MST

星途 面试题库

面试题:C++智能指针的内存管理与循环引用问题

假设有两个类A和B,A类中有一个std::shared_ptr<B>成员变量,B类中有一个std::shared_ptr<A>成员变量,这样可能会导致循环引用。请描述循环引用带来的问题,并给出至少两种解决循环引用的方法,同时用代码示例说明。
17.1万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

循环引用带来的问题

循环引用会导致内存泄漏。当两个对象通过std::shared_ptr相互引用时,它们的引用计数永远不会归零,即使程序中不再有其他地方引用这两个对象,它们占用的内存也无法被释放。

解决循环引用的方法

  1. 使用std::weak_ptrstd::weak_ptr是一种不控制对象生命周期的智能指针,它指向由std::shared_ptr管理的对象,但不会增加对象的引用计数。当std::shared_ptr管理的对象被释放后,指向它的std::weak_ptr会自动失效。
#include <iostream>
#include <memory>

class B;

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

class B {
public:
    std::weak_ptr<A> a_weak_ptr;
    ~B() {
        std::cout << "B destroyed" << std::endl;
    }
};
  1. 手动打破循环:在适当的时候手动将其中一个std::shared_ptr设置为nullptr,以打破循环引用。
#include <iostream>
#include <memory>

class B;

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

class B {
public:
    std::shared_ptr<A> a_ptr;
    ~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->b_ptr = b;
    b->a_ptr = a;

    // 手动打破循环
    a->b_ptr = nullptr;
    b->a_ptr = nullptr;

    return 0;
}

当手动将a->b_ptrb->a_ptr设置为nullptr后,ab的引用计数会归零,它们所占用的内存会被正确释放。