C++特性之智能指针shared_ptr详解
什么是智能指针?
智能指针是C ++中的一个重要特性,它可以避免内存泄漏和悬空指针的问题。智能指针是一个C ++类,它的析构函数自动释放分配的内存。最常见的智能指针有:
- unique_ptr
- shared_ptr
- weak_ptr
其中shared_ptr是引用计数智能指针。这种智能指针在控制对象之间的共享所有权方面非常有用。它使用引用计数来跟踪有多少个指针指向同一个对象,并在不需要它时自动删除对象。
shared_ptr的使用方法
shared_ptr是一个模板类,它和unique_ptr一样,通常使用std命名空间。我们来看一下shared_ptr的使用方法。
向shared_ptr分配内存的方式有两种,一种是通过new运算符直接进行内存分配,另一种是通过std::make_shared函数进行分配。
通过new运算符分配内存的方式
std::shared_ptr<int> p1(new int(10));
std::shared_ptr<std::string> p2(new std::string("hello shared_ptr"));
在上述例子中,我们使用了new运算符来分配内存,并将其传递给shared_ptr构造函数。通过new运算符分配内存的方式需要显式释放内存,不然会导致内存泄漏。当使用shared_ptr管理指针时,不需要显示调用delete函数释放内存。
通过std::make_shared函数分配内存的方式
auto p3 = std::make_shared<int>(10);
auto p4 = std::make_shared<std::string>("hello shared_ptr");
使用std::make_shared函数可以更加方便的分配内存,这种方式不需要显式的释放内存,因为智能指针会自动进行管理,并在对象不再被使用时释放对象所占用的内存。
shared_ptr的拷贝和移动
shared_ptr是一个指向对象的指针,多个shared_ptr可以指向同一个对象。每个shared_ptr都有一个引用计数器,当有一个新的shared_ptr指向该对象时,计数器值加一。当任意一个shared_ptr生命周期结束时,计数器值减一。只有当计数器值为零时,才会释放对象的内存。
下面我们看一个简单的例子.
#include <iostream>
#include <memory>
int main() {
auto p1 = std::make_shared<int>(10);
std::cout << "p1 count:" << p1.use_count() << std::endl;
{
auto p2 = p1;
std::cout << "p1 count:" << p1.use_count() << std::endl;
std::cout << "p2 count:" << p2.use_count() << std::endl;
}
std::cout << "p1 count:" << p1.use_count() << std::endl;
return 0;
}
输出结果如下所示:
p1 count:1
p1 count:2
p2 count:2
p1 count:1
该程序分别创建了两个shared_ptr,p1和p2,它们都指向同一个整型对象。在创建p2时,p2指向p1所指向的对象,并且两者拥有相同的计数器。当内部作用域结束时,p2被销毁并计数器减一,但p1仍然存在,因此p1的计数器不为零。在程序结束时,p1销毁并计数器减一,因此计数器为零,整型对象被销毁。
shared_ptr可以通过拷贝和移动进行赋值,下面我们来看一下拷贝和移动的用法。
#include <iostream>
#include <memory>
int main() {
auto p1 = std::make_shared<int>(10);
std::cout << "p1 count:" << p1.use_count() << std::endl;
auto p2(p1);
std::cout << "p1 count:" << p1.use_count() << std::endl;
std::cout << "p2 count:" << p2.use_count() << std::endl;
auto p3 = std::move(p1);
std::cout << "p1 count:" << p1.use_count() << std::endl;
std::cout << "p3 count:" << p3.use_count() << std::endl;
return 0;
}
输出结果如下所示:
p1 count:1
p1 count:2
p2 count:2
p1 count:0
p3 count:2
在上面的例子中,首先创建共享指针p1并将其数量计为1。然后通过拷贝构造函数创建了两个新的共享指针p2和p1,并将其数值增加至2。接下来,使用std::move操作将p1的所有权转移给p3,并使p1指向null。此时,p3和p2计数器的值都为2,而p1指向null。
shared_ptr的示例说明
下面是一个使用shared_ptr管理动态数组的示例:
#include <iostream>
#include <memory>
int main() {
auto p1 = std::make_shared<int[]>(3);
p1[0] = 10;
p1[1] = 20;
p1[2] = 30;
for (int i = 0; i < 3; i++) {
std::cout << "p1[" << i << "]=" << p1[i] << std::endl;
}
return 0;
}
上面的代码创建了一个动态数组,并使用shared_ptr管理动态数组的内存。我们可以像使用原生数组一样来操作p1,包括访问元素和遍历。当程序结束时,p1所占用的内存会自动释放。
下面是一个示例,使用shared_ptr构建一个类的实例。
#include <iostream>
#include <memory>
class A {
public:
A(int a) : a(a) {}
void print() {
std::cout << "a=" << a << std::endl;
}
private:
int a;
};
int main() {
auto p1 = std::make_shared<A>(10);
p1->print();
return 0;
}
上面的代码创建了一个类A的实例,并使用shared_ptr管理对象的内存。我们可以像使用原生指针一样来操作p1,包括调用成员函数和访问成员变量。当程序结束时,p1所占用的内存会自动释放。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++特性之智能指针shared_ptr详解 - Python技术站