智能指针的定义
在 C++ 中,智能指针是一种类模板,用于管理动态分配的内存。它的主要目的是自动管理内存的生命周期,避免手动释放内存时可能出现的错误,如内存泄漏(忘记释放内存)和悬空指针(访问已释放的内存)。智能指针通过重载*(解引用运算符)和->(成员访问运算符)等运算符,使得它在行为上类似于普通指针,但又具有自动内存管理的功能。
例如,在没有智能指针的情况下,使用普通指针分配内存如下:
int* ptr = new int;
// 使用ptr
delete ptr; // 需要手动释放内存,如果忘记就会导致内存泄漏
而智能指针可以自动处理内存的释放,减少这种错误的发生。
智能指针的类型
std::unique_ptr独占所有权:
std::unique_ptr是一种独占式智能指针,它所管理的对象只能有一个unique_ptr与之关联。这意味着当一个unique_ptr拥有一个对象的所有权时,其他unique_ptr不能同时拥有该对象。
示例:
#include <memory>
int main() {
std::unique_ptr<int> ptr1 = std::make_unique<int>(5);
// std::unique_ptr<int> ptr2 = ptr1; // 这是错误的,不能复制unique_ptr
std::unique_ptr<int> ptr3 = std::move(ptr1); // 通过移动语义转移所有权
return 0;
}
资源所有权转移:
它通过移动语义(std::move函数)来转移资源的所有权。当一个unique_ptr被移动到另一个unique_ptr后,原来的unique_ptr就不再拥有该资源,其内部指针变为nullptr。这种机制保证了对象的独占性,并且符合 C++ 的零开销原则,因为没有额外的引用计数等开销。
std::shared_ptr共享所有权:
std::shared_ptr实现了共享式的所有权管理。多个shared_ptr可以同时指向同一个对象,对象的生命周期会一直持续到最后一个指向它的shared_ptr被销毁。
引用计数机制:
它内部使用引用计数来记录有多少个shared_ptr指向同一个对象。每当一个新的shared_ptr指向该对象时,引用计数加 1;当一个shared_ptr被销毁(例如超出作用域)时,引用计数减 1。当引用计数变为 0 时,所管理的对象会被自动删除。
#include <memory>
int main() {
std::shared_ptr<int> ptr1 = std::make_shared<int>(10);
std::shared_ptr<int> ptr2 = ptr1; // 共享所有权,引用计数变为2
return 0;
}
// 当main函数结束,ptr1和ptr2都超出作用域,引用计数减为0,对象被自动删除
std::weak_ptr弱引用:
std::weak_ptr是一种弱引用智能指针,它主要用于解决std::shared_ptr可能出现的循环引用问题。weak_ptr不控制对象的生命周期,它只是对一个由shared_ptr管理的对象的弱引用。
与shared_ptr的关系:weak_ptr可以通过lock函数来获取一个指向相同对象的shared_ptr,如果对象已经被释放(引用计数为 0),则lock函数返回一个空的shared_ptr。
循环引用示例及解决方法:
假设有两个类A和B,它们相互包含shared_ptr成员,可能会导致循环引用
class B;
class A {
public:
std::shared_ptr<B> b;
A() {}
~A() {}
};
class B {
public:
std::shared_ptr<A> a;
B() {}
~B() {}
};
int main() {
std::shared_ptr<A> a = std::make_shared<A>();
std::shared_ptr<B> b = std::make_shared<B>();
a->b = b;
b->a = a;
// 这里a和b的引用计数都为2,当main函数结束时,它们的引用计数无法减为0,导致内存泄漏,无法调用a,b的析构函数
// 使用weak_ptr解决
class B;
class A {
public:
std::weak_ptr<B> b;
A() {}
~A() {}
};
class B {
public:
std::weak_ptr<A> a;
B() {}
~B() {}
};
std::shared_ptr<A> a = std::make_shared<A>();
std::shared_ptr<B> b = std::make_shared<B>();
a->b = b;
b->a = a;
// 这样就不会出现循环引用导致的内存泄漏问题
return 0;
}
标签:std,C++,智能,引用,shared,unique,ptr,指针
From: https://blog.csdn.net/2202_75941514/article/details/143980886