引用

c++ 11:

  • std::shared_ptr

前言

shared顾名思义就是共享的意思,这个共享指针当然也属于智能指针这一块。

语法上:
std::shared_ptr<type> tyename
例如:
std::shared_ptr<int> a{}
std::shared_ptr<int> b{ std::make_shared<int>(0) }
注意:std::make_shared不支持数组
std::shared_ptr<int[]> c{ new int[5]{1,2,3,4,5} }


正文

1
2
3
4
5
std::shared_ptr<int[]> sp{new int[5]{1,2,3,4,5}};
std::shared_ptr<int> sp1{ std::make_shared<int>(5) };

std::cout << sp[0] << std::endl;
std::cout << sp1[0] << std::endl; //与unique一样,初始化时是单个int则无法使用[]调用

回到起点,shared是共享的意思,也就是说,共享指针是可以被其他共享指针所指向的。

1
2
3
4
5
6
7
std::shared_ptr<int> sp1{ std::make_shared<int>(5) };
std::shared_ptr<int> sp2{ sp1 };
std::shared_ptr<int> sp3{ sp1 };

std::cout << sp1 << " " << *sp1 << std::endl;
std::cout << sp2 << " " << *sp2 << std::endl;
std::cout << sp3 << " " << *sp3 << std::endl;

可以看到sp2和sp3的地址和地址上的值都与sp1一致。


user_count

如果有多个共享指针指向同一地址,那么只有最后一个共享指针释放内存的时候,才能真正释放所占用的内存空间,也就这个原因,导致shared_ptr会记录这个地址被多少个智能指针调用。
有记录的属性,也就意味着shared_ptr会占用的更多内存。

查看的方式也很简单,就是调用.user_count()

比如上面的代码,我们调用一个试试:
共享属性所以.user_count()在sp1或者2和3上得到的都是一个结果,因为它们指向同一块内存。


unique

能统计就能判断是否被其他指针调用。
利用.unique()获取一个智能指针是否是唯一拥有该地址的。
注:unique返回的是bool类型的值

这里是sp1、2、3自然不用多想都是0,也就是false。

另外值得一提的是,因为这个功能稍显鸡肋,c++17的时候把它废除了。。。。。


reset

在user_cout的时候说了一下,shared_ptr指针指向的内存空间只有当最后一个指向它的shared_ptr指针去释放的时候才会真正被释放掉,不然其余几个释放只是将自己置为nullptr。

1
2
3
4
5
6
7
8
9
10
11
12
13
std::shared_ptr<int> sp1{ std::make_shared<int>(5) };
std::shared_ptr<int> sp2{ sp1 };
std::shared_ptr<int> sp3{ sp1 };

std::cout << sp1 << std::endl;
std::cout << sp2 << std::endl;
std::cout << sp3 << std::endl;

sp1.reset();

std::cout << sp1 << std::endl;
std::cout << sp2 << std::endl;
std::cout << sp3 << std::endl;

能看到sp1自己被置空了,sp2和sp3仍然指向sp1之前指向的内存地址。
再把sp2reset掉后也是一个样子
所以说只有将最后一个指向那片内存区域的指针释放了才是真正意义上的释放内存空间

当然如果有一定怀疑,还可以在reset前后看看use_count的情况

例如sp1和sp2都被reset了,能看到sp3指向的内存区域现在就只有一个指针指向它。


结语

没啥心得体会,就是感觉shared_ptr在内存占用上要么高一点,要么有一部分内存都写了特定的东西了,就比如说统计多少个指向这块内存的指针。