5.2 共享指针
共享指针(shared_ptr)是使用引用计数的方式来管理指向的对象的智能指针,它允许多个智能指针来管理同一个动态创建的对象。只有多个指针都销毁的情况下才会销毁(delete)被管理的对象。
共享指针原理
当用第一次用共享指针来管理一个对象时,此共享指针会动态创建一个整数的内存区域并将其初始化为1,这个整数对象用来记录指向当前被管理对象的智能指针的个数,此整数由所有管理此对象的智能指针所共享,并由最后管理此对象的智能指针所释放。这个整数用来引用计数,即记录指向此被管理对象的智能指针的个数。
语法
// 创建共享指针并直接管理单个对象
std::shared_ptr<类> ptr(new 类(构造函数实参1, 构造函数实参2, ...));
// 创建共享指针并直接管理多个对象的数组
std::shared_ptr<类[]> ptr(new 类[元素个数]{...});
// 创建空共享指针
std::shared_ptr<类> ptr;
常用成员函数
成员函数
说明
reset重新设定管理对象指针,旧的管理对象的引用计数减一,新的管理对象的引用计数加一。
swap交换两个同类型智能指针管理的对象。
get返回管理对象的普通指针。
use_count返回管理对象的引用计数。
operator bool判断是否为空指针。
operator =修改共享指针的指向。
示例
// filename: shared_ptr.cpp
#include <iostream>
#include <memory>
using namespace std;
class Point {
public:
Point(float ax=0, float ay=0):x(ax), y(ay) {
cout << "Point(" << x << "," << y << ")\n";
}
~Point() {
cout << "~Point(" << x << "," << y << ")\n";
}
// 定义为虚函数
void info(void) {
cout << "点(" << x << "," << y << ")\n";
}
public:
float x;
float y;
};
shared_ptr<Point> get_point() {
shared_ptr<Point> ptr(new Point(5.1, 5.2)); // 引用计数为1
return ptr;// 此 ptr 会作为调用的表达式返回。
}
int main(int argc, char * argv[]) {
std::cout << "-- 进入 main 函数 --" << std::endl;
{
std::cout << "- 进入内部作用域 -" << std::endl;
shared_ptr<Point> ptr1(new Point(1.1, 1.2)); // Point(1.1, 1.2)引用计数为1
shared_ptr<Point> ptr2(new Point(2.1, 2.2));
ptr2 = ptr1; // Point(2.1, 2.2)被释放Point(1.1, 1.2) 引用计数为2
shared_ptr<Point[]> ptr3(new Point[2]{Point(3.1, 3.2), Point(4.1, 4.2)});
shared_ptr<Point> ptr4;
ptr4 = get_point();
// 使用 -> 访问成员
ptr1->info();
ptr2->info();
ptr4->info();
// 使用 * 解引用
(*ptr1).info();
(*ptr2).info();
(*ptr4).info();
cout << "ptr1的引用计数:" << ptr1.use_count() << endl;
cout << "ptr2的引用计数:" << ptr2.use_count() << endl;
cout << "ptr3的引用计数:" << ptr3.use_count() << endl;
cout << "ptr4的引用计数:" << ptr4.use_count() << endl;
cout << "- 即将离开内部作用域 -" << endl;
} // 离开作用域,ptr1 自动调用析构函数,内存被释放
cout << "-- 已离开内部作用域 --" << endl;
return 0;
}
编译和运行结果如下:
weimz@mzstudio:~/old$ g++ -o shared_ptr shared_ptr.cpp
weimz@mzstudio:~/old$ ./shared_ptr
-- 进入 main 函数 --
- 进入内部作用域 -
Point(1.1,1.2)
Point(2.1,2.2)
~Point(2.1,2.2)
Point(3.1,3.2)
Point(4.1,4.2)
Point(5.1,5.2)
点(1.1,1.2)
点(1.1,1.2)
点(5.1,5.2)
点(1.1,1.2)
点(1.1,1.2)
点(5.1,5.2)
ptr1的引用计数:2
ptr2的引用计数:2
ptr3的引用计数:1
ptr4的引用计数:1
- 即将离开内部作用域 -
~Point(5.1,5.2)
~Point(4.1,4.2)
~Point(3.1,3.2)
~Point(1.1,1.2)
-- 已离开内部作用域 --