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)
-- 已离开内部作用域 --