什么是智能指针
智能指针是一种 C++ 标准库中的模板类,用于管理动态分配内存资源。它们提供了自动化的内存管理功能,可以帮助程序员在避免内存泄漏和野指针的同时,简化内存资源的手动释放。C++ 标准库中提供了三种主要的智能指针:std::shared_ptr、std::unique_ptr 和 std::weak_ptr。
智能指针的原理
shared_ptr采用了引用计数器,允许多个指针指向同一个对象。每一个shared_ptr的拷贝都指向相同的内存,并共同维护同一个引用计数器,记录同一个实例被引用的次数。每使用他一次,内部的引用计数加1,每析构一次,内部的引用计数减1,减为0时,自动删除所指向的堆内存。shared_ptr内部的引用计数是线程安全的,但是对象的读取需要加锁。
1、std::shared_ptr:
- shared_ptr在内部会维护着一份引用计数,用来记录该份资源被几个对象共享。
- 当一个shared_ptr对象被销毁时(调用析构函数),析构函数内就会将该计数减1。
- 如果引用计数减为0后,则表示自己是最后一个使用该资源的shared_ptr对象,必须释放资源。
- 如果引用计数不是0,就说明自己还有其他对象在使用,则不能释放该资源,否则其他对象就成为野指针。
class MyClass {
public:
std::shared_ptr<MyClass> ptr;
MyClass() {
std::cout << "构造函数" << std::endl;
}
~MyClass() {
std::cout << "析构函数" << std::endl;
}
};
int main(int argc, char argv)
{
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::shared_ptr<MyClass> ptr2 = std::make_shared<MyClass>();
return 0;
}
输出结果:
注意,在使用std::shared_ptr有可能导致循环引用问题,如:
class MyClass {
public:
std::shared_ptr<MyClass> ptr;
MyClass() { std::cout << "构造函数" << std::endl; }
~MyClass() { std::cout << "析构函数" << std::endl; }
};
int main() {
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::shared_ptr<MyClass> ptr2 = std::make_shared<MyClass>();
ptr1->ptr = ptr2; // ptr1 持有 ptr2 的引用
ptr2->ptr = ptr1; // ptr2 持有 ptr1 的引用
std::cout << ptr1.use_count() << std::endl;
std::cout << ptr2.use_count() << std::endl;
return 0;
}
输出结果:
2、std::unique_ptr:
- std::unique_ptr 是一种独占所有权的智能指针,确保只有一个指针指向一个对象。
- 它直接将拷贝构造函数和赋值重载函数给禁用掉,因此,不让其进行拷贝和赋值。
- 它通过将所有权转移给新指针或释放给定对象来管理动态内存。
class MyClass {
public:
MyClass() { std::cout << "构造函数" << std::endl; }
~MyClass() { std::cout << "析构函数" << std::endl; }
void function() { std::cout << "函数调用" << std::endl; };
};
int main(int argc, char argv)
{
std::unique_ptr<MyClass> ptr1 = std::make_unique<MyClass>();
// std::unique_ptr<MyClass> ptr2 = ptr1; // 报错
// 不能直接进行拷贝,但可以进行移动赋值
std::unique_ptr<MyClass> ptr2 = std::move(ptr1);
ptr2->function();
return 0;
}
输出结果:
3、std::weak_ptr:
- std::weak_ptr 是一种弱引用智能指针,不会增加对象的引用计数。
- 它通常用于解决循环引用的问题,通过检查对象是否仍然存在来避免访问无效的指针。
class MyClass {
public:
std::shared_ptr<MyClass> ptr;
MyClass() { std::cout << "构造函数" << std::endl; }
~MyClass() { std::cout << "析构函数" << std::endl; }
void function() { std::cout << "函数调用" << std::endl; };
};
int main(int argc, char argv)
{
std::shared_ptr<MyClass> ptr1 = std::make_shared<MyClass>();
std::weak_ptr<MyClass> ptr2 = ptr1;
std::cout << "ptr1 user count = " << ptr1.use_count() << std::endl;
if (auto lockedPtr = ptr2.lock())
lockedPtr->function();
else
std::cout << "对象已被释放" << std::endl;
return 0;
}
输出结果: