网站建设 今晟网络,给你一个网站怎么做,宁波制作网站哪个好,成都品牌建设网站公司智能指针shared_ptr详解 一、简介二、底层原理2.1、引用计数2.2、shared_ptr的构造和析构2.3、shared_ptr的共享和拷贝2.4、循环引用问题 三、shared_ptr的使用3.1、创建一个shared_ptr3.2、共享一个shared_ptr3.3、使用删除器3.4、解除关联 四、使用示例总结 一、简介
C智能指… 智能指针shared_ptr详解 一、简介二、底层原理2.1、引用计数2.2、shared_ptr的构造和析构2.3、shared_ptr的共享和拷贝2.4、循环引用问题 三、shared_ptr的使用3.1、创建一个shared_ptr3.2、共享一个shared_ptr3.3、使用删除器3.4、解除关联 四、使用示例总结 一、简介
C智能指针shared_ptr是一种可以自动管理内存的智能指针它是C11新增的特性之一。与传统指针不同shared_ptr可以自动释放所管理的动态分配对象的内存并避免了手动释放内存的繁琐操作从而减少了内存泄漏和野指针的出现。
shared_ptr是一个模板类通过引用计数器实现多个智能指针共享对一个对象的所有权。每次复制一个shared_ptr对象时该对象的引用计数器会增加1当最后一个shared_ptr对象被销毁时引用计数器减1如果引用计数器变为0则释放所管理的对象的内存。
使用shared_ptr需要包含头文件并且可以通过以下方式创建
std::shared_ptrint p(new int(10));上面的代码创建了一个shared_ptr对象p它指向一个动态分配的int类型对象初始值为10。
在使用shared_ptr时需要注意以下几点 不要使用裸指针来初始化shared_ptr否则可能导致多次删除同一个对象的情况。 避免在shared_ptr中存储数组因为shared_ptr只能处理单个对象的释放而不能正确地处理数组的销毁。 可以通过自定义删除器deleter来实现对对象的特定方式的释放。 shared_ptr可以作为函数参数传递但要注意避免循环引用的问题否则会导致内存泄漏。
shared_ptr是一种方便且安全的内存管理工具能够有效地避免内存泄漏和野指针的出现。
二、底层原理 2.1、引用计数
shared_ptr的核心是引用计数技术。在每个shared_ptr对象中都有一个指向所管理对象的指针和一个整型计数器。这个计数器统计有多少个shared_ptr对象指向该所管理对象。当一个新的shared_ptr对象指向同一块内存时该内存的引用计数就会增加1。当一个shared_ptr对象不再指向该内存时该内存的引用计数就会减少1。当引用计数为0时说明没有任何shared_ptr对象指向该内存此时该内存将会被自动释放。
2.2、shared_ptr的构造和析构 shared_ptr的构造函数需要一个指针作为参数该指针指向要被管理的对象。当一个新的shared_ptr对象被创建时它会尝试增加所管理对象的引用计数。如果该对象还未被其他shared_ptr对象管理则会创建一个新的引用计数并将其设置为1。否则它会与已经存在的shared_ptr对象共享同一个引用计数。 shared_ptr的析构函数会尝试减少所管理对象的引用计数。如果引用计数变成0则会自动释放所管理对象的内存。 shared_ptr的控制块包含引用计数和删除器等信息会在最后一个指向所管理对象的shared_ptr析构时被释放。当引用计数减为0时就说明没有任何shared_ptr对象指向该所管理对象了此时shared_ptr会自动调用删除器并释放掉控制块。由于shared_ptr可以共享同一个控制块因此只有所有shared_ptr对象都析构后控制块才能被释放。如果一个shared_ptr对象使用reset()方法手动解除与所管理对象的关联也会相应地减少引用计数当引用计数变成0时控制块也会被释放。
2.3、shared_ptr的共享和拷贝
shared_ptr可以与其他shared_ptr对象共享同一个指向对象的指针。当一个shared_ptr对象被复制时它所管理的对象的引用计数也会增加1。因此任何一个持有相同指针的shared_ptr对象都可以通过更改其所管理对象的状态来影响所有其他shared_ptr对象。
2.4、循环引用问题
shared_ptr在处理循环引用问题时非常有效。例如如果一个对象A包含指向另一个对象B的shared_ptr而对象B也包含指向对象A的shared_ptr则这两个对象将形成循环引用。在这种情况下如果使用普通指针可能会出现内存泄漏。但是由于shared_ptr使用引用计数技术当没有任何其他shared_ptr对象引用这两个对象时它们将被正确地释放。
三、shared_ptr的使用
创建shared_ptr对象的语法有以下几种方式
通过new关键字创建
std::shared_ptrint p(new int);通过make_shared函数创建该函数可以避免使用new关键字
std::shared_ptrint p std::make_sharedint();传递指针和删除器作为参数创建
void my_deleter(int* p) {delete p;
}std::shared_ptrint p(new int, my_deleter);传递指针、删除器和分配器作为参数创建
void my_deleter(int* p) {delete p;
}struct MyAllocator {void* allocate(size_t size);void deallocate(void* ptr, size_t size);
};MyAllocator my_allocator;std::shared_ptrint p(new int, my_deleter, my_allocator);从另一个shared_ptr对象创建
std::shared_ptrint p1(new int);
std::shared_ptrint p2(p1);使用移动语义从另一个shared_ptr对象创建
std::shared_ptrint p1(new int);
std::shared_ptrint p2(std::move(p1));3.1、创建一个shared_ptr
使用shared_ptr创建一个智能指针非常简单只需要将一个指向动态分配内存的裸指针作为参数传递给shared_ptr的构造函数即可
// 创建一个int类型的智能指针
std::shared_ptrint p(new int(10));3.2、共享一个shared_ptr
shared_ptr可以与其他shared_ptr对象共享同一个指向对象的指针这样就可以避免多次动态分配内存和释放内存的问题。共享一个shared_ptr可以通过复制构造函数和赋值运算符实现
// 复制构造函数
std::shared_ptrint p1(new int(10));
std::shared_ptrint p2(p1);// 赋值运算符
std::shared_ptrint p3(new int(10));
std::shared_ptrint p4;
p4 p3;注意共享一个shared_ptr会增加所管理对象的引用计数。因此任何一个持有相同指针的shared_ptr对象都可以通过更改其所管理对象的状态来影响所有其他shared_ptr对象。
3.3、使用删除器
除了管理所分配的内存外shared_ptr还可以使用删除器deleter来管理对象。删除器是一个函数或者函数对象用于在shared_ptr释放所管理对象时执行特定的操作。删除器可以通过shared_ptr的模板参数指定
// 使用Lambda表达式作为删除器
std::shared_ptrint p(new int(10), [](int* p){ delete[] p; });3.4、解除关联
如果需要解除shared_ptr与所管理对象的关联可以使用reset()方法
std::shared_ptrint p(new int(10));
p.reset();注意当调用reset()方法后所管理对象的引用计数会减少1。如果引用计数变成0则会自动释放所管理对象的内存。
四、使用示例
#include memory
#include iostreamusing namespace std;class MyClass {
public:MyClass() { cout MyClass constructor endl; }~MyClass() { cout MyClass destructor endl; }void printInfo() { cout This is MyClass endl; }
};int main() {shared_ptrMyClass p1(new MyClass()); // 创建一个shared_ptr指向MyClass对象shared_ptrMyClass p2 p1; // p1和p2都指向同一个MyClass对象p1-printInfo(); // 访问MyClass对象的成员函数p2.reset(); // 释放p2所指向的MyClass对象p1-printInfo(); // 由于p1仍然指向MyClass对象所以此处输出This is MyClassreturn 0;
}上述代码中通过调用shared_ptrMyClass构造函数创建了两个指针p1和p2并且它们都指向一个MyClass对象。我们调用reset()函数来释放p2所指向的MyClass对象但是由于p1仍然指向该对象所以在调用p1-printInfo()时仍然输出This is MyClass。当程序结束时p1所指向的MyClass对象会被自动释放。
可以看到使用shared_ptr可以很方便地避免内存泄漏和悬空指针等问题。另外需要注意的是shared_ptr指针之间的赋值和拷贝操作都会增加指向对象的引用计数即使一个指针已经释放了它所指向的对象只要其他指针还在使用该对象该对象就不会被自动删除。因此在使用shared_ptr时需要注意对象的生命周期避免产生意外的副作用。
总结
智能指针是C中一种重要的语言机制其中shared_ptr是最常用和最经典的智能指针之一。 shared_ptr是一种引用计数的智能指针可以共享同一个对象。 使用shared_ptr时需要包含头文件 memory 。 创建shared_ptr对象时可以直接将原始指针作为参数传递给构造函数也可以使用make_shared函数进行创建。 对象的引用计数会在shared_ptr对象初始化、复制、释放时自动更新。 当某个shared_ptr对象被销毁时它所指向的对象的引用计数会减少如果引用计数为0则该对象会被自动删除。 通过get函数可以获取shared_ptr对象所管理的原始指针。 通过reset函数可以重新绑定shared_ptr对象所管理的原始指针。 可以使用unique函数判断shared_ptr对象是否唯一拥有原始指针。 通常情况下shared_ptr对象应该在栈上创建而不是使用new运算符在堆上创建。 在多线程环境下使用shared_ptr时需要注意需要采取线程安全措施比如使用锁来保证引用计数的正确性。 shared_ptr是C11中STL的一部分它是一个模板类用于管理动态地分配对象的内存。shared_ptr可以自动完成内存管理确保内存被正确释放并且非常易于使用。 shared_ptr是一个强大的智能指针类它利用引用计数技术来管理动态分配的对象的内存。shared_ptr可以避免循环引用和内存泄漏等问题并且易于使用是C程序员必不可少的工具之一。