shared_ptr 是一种智能指针,用于自动管理动态分配的对象的生命周期。它通过引用计数机制来确保当最后一个 shared_ptr 指向一个对象时,该对象会被自动销毁。
当两个或多个 shared_ptr 实例相互引用时,会形成一个环形引用,导致引用计数永远不会达到零,从而引起内存泄漏。
#include
#include
class B; // 前向声明
class A {
public:
std::shared_ptr b_ptr;
~A() {
std::cout << "A destructor called" << std::endl;
}
};
class B {
public:
std::shared_ptr a_ptr;
~B() {
std::cout << "B destructor called" << std::endl;
}
};
int main() {
std::shared_ptr a = std::make_shared();
std::shared_ptr b = std::make_shared();
a->b_ptr = b;
b->a_ptr = a;
return 0;
}
在这个例子中,A 的实例持有 B 的一个 shared_ptr,而 B 的实例也持有 A 的一个 shared_ptr。这导致它们的引用计数永远不会降到零,因此它们的析构函数永远不会被调用,从而造成内存泄漏。
使用 std::weak_ptr
std::weak_ptr 是一种智能指针,它不会增加对象的引用计数。它设计用来解决 shared_ptr 的环形引用问题。你可以将其中一个对象的 shared_ptr 替换为 weak_ptr 来避免环形引用:
#include
#include
class B; // 前向声明
class A {
public:
std::weak_ptr b_ptr; // 使用 weak_ptr 替代 shared_ptr
~A() {
std::cout << "A destructor called" << std::endl;
}
};
class B {
public:
std::shared_ptr a_ptr;
~B() {
std::cout << "B destructor called" << std::endl;
}
};
int main() {
std::shared_ptr a = std::make_shared();
std::shared_ptr b = std::make_shared();
a->b_ptr = b;
b->a_ptr = a;
return 0;
}
在这个修改后的例子中,A 类使用 std::weak_ptr 来引用 B 类的实例。这样,A 对 B 的引用不会增加 B 的引用计数。因此,当 main 函数结束时,a 和 b 的引用计数都会降到零,它们所指向的对象将被正确销毁,从而避免了内存泄漏。
weak_ptr 是一种智能指针,用于观察 std::shared_ptr 所管理的对象,但不拥有该对象。std::weak_ptr 不会增加对象的引用计数,因此不会影响对象的生命周期。它主要用于解决 std::shared_ptr 的环形引用问题。
#include
#include
class Widget {
public:
Widget() { std::cout << "Widget constructed\n"; }
~Widget() { std::cout << "Widget destroyed\n"; }
};
int main() {
std::shared_ptr sharedPtr = std::make_shared();
std::weak_ptr weakPtr = sharedPtr;
std::cout << "Shared count: " << sharedPtr.use_count() << std::endl; // 输出 1
if (auto tempSharedPtr = weakPtr.lock()) { // 尝试从 weak_ptr 获取 shared_ptr
std::cout << "Object is alive\n";
} else {
std::cout << "Object is destroyed\n";
}
sharedPtr.reset(); // 释放 shared_ptr 所有权
if (auto tempSharedPtr = weakPtr.lock()) { // 再次尝试获取
std::cout << "Object is alive\n";
} else {
std::cout << "Object is destroyed\n"; // 此时输出
}
return 0;
}
unique_ptr 是一种智能指针,它提供对单一对象的独占所有权。这意味着 std::unique_ptr 实例拥有它所指向的对象,并且不允许复制该智能指针,只允许移动。当 std::unique_ptr 被销毁时,它所指向的对象也会被自动销毁。
#include
#include
class Widget {
public:
Widget() { std::cout << "Widget constructed\n"; }
~Widget() { std::cout << "Widget destroyed\n"; }
};
int main() {
std::unique_ptr widgetPtr = std::make_unique();
// std::unique_ptr anotherPtr = widgetPtr; // 编译错误,不能复制
std::unique_ptr movedPtr = std::move(widgetPtr); // 移动是允许的
return 0;
}