std::unique_ptr
- 原理:
std::unique_ptr
是一种独占所有权的智能指针,同一时间只有一个 std::unique_ptr
可以指向一个对象。当 std::unique_ptr
离开其作用域或被显式释放时,它所指向的对象会被自动销毁,即调用对象的析构函数。
- 代码示例:
#include <iostream>
#include <memory>
class MyClass {
public:
~MyClass() {
std::cout << "MyClass destructor called" << std::endl;
}
};
int main() {
{
std::unique_ptr<MyClass> ptr(new MyClass());
} // 当ptr离开这个作用域,MyClass的析构函数被调用
return 0;
}
std::shared_ptr
- 原理:
std::shared_ptr
允许多个智能指针共享同一个对象的所有权。它使用引用计数来管理对象的生命周期,当引用计数降为0时,所指向的对象会被自动销毁,调用其析构函数。
- 代码示例:
#include <iostream>
#include <memory>
class MyClass {
public:
~MyClass() {
std::cout << "MyClass destructor called" << std::endl;
}
};
int main() {
{
std::shared_ptr<MyClass> ptr1(new MyClass());
std::shared_ptr<MyClass> ptr2 = ptr1;
} // 当ptr1和ptr2都离开作用域,引用计数降为0,MyClass的析构函数被调用
return 0;
}
- 循环引用问题:当两个或多个
std::shared_ptr
之间形成循环引用时,引用计数永远不会降为0,导致内存泄漏。
#include <iostream>
#include <memory>
class B;
class A {
public:
std::shared_ptr<B> b;
~A() {
std::cout << "A destructor called" << std::endl;
}
};
class B {
public:
std::shared_ptr<A> a;
~B() {
std::cout << "B destructor called" << std::endl;
}
};
int main() {
{
std::shared_ptr<A> ptrA(new A());
std::shared_ptr<B> ptrB(new B());
ptrA->b = ptrB;
ptrB->a = ptrA;
} // 这里A和B的析构函数都不会被调用,造成内存泄漏
return 0;
}
std::weak_ptr
- 原理:
std::weak_ptr
是一种弱引用,它指向由 std::shared_ptr
管理的对象,但不会增加对象的引用计数。std::weak_ptr
主要用于解决 std::shared_ptr
的循环引用问题。
- 解决循环引用代码示例:
#include <iostream>
#include <memory>
class B;
class A {
public:
std::weak_ptr<B> b;
~A() {
std::cout << "A destructor called" << std::endl;
}
};
class B {
public:
std::weak_ptr<A> a;
~B() {
std::cout << "B destructor called" << std::endl;
}
};
int main() {
{
std::shared_ptr<A> ptrA(new A());
std::shared_ptr<B> ptrB(new B());
ptrA->b = ptrB;
ptrB->a = ptrA;
} // 此时A和B的析构函数会被调用,避免了内存泄漏
return 0;
}
总结
- std::unique_ptr:适合独占资源场景,析构函数在离开作用域或手动释放时调用。
- std::shared_ptr:用于共享资源场景,但要注意循环引用问题。
- std::weak_ptr:配合
std::shared_ptr
使用,解决循环引用问题,确保析构函数按预期执行,避免内存泄漏。