简介

shared_ptr是一种通过指针保持对象共享所有权的智能指针。多个 shared_ptr 对象可持有同一对象。下列情况之一出现时销毁对象并解分配其内存

  • 最后剩下的持有对象的 shared_ptr 被销毁
  • 最后剩下的持有对象的 shared_ptr 被通过operator=reset()赋值为另一指针

成员函数

观察器

1
2
3
T* get();					// 返回引用对象的原始指针
int use_count(); // 返回 shared_ptr 所指对象的引用计数
bool unique(); // 检查所管理对象是否仅由当前 shared_ptr 的对象管理

swap

交换*thisr的存储指针值与所有权。不调整引用计数(若它们存在)

1
void swap(shared_ptr& r);

reset

[1]释放被管理对象的所有权

调用后*this不管理对象。等价于shared_ptr().swap(*this);(空对象与当前智能指针交换管理权)

1
2
3
4
5
6
7
8
9
10
11
12
13
void reset();				// 释放该智能指针, 使智能指针的引用数-1, 当引用数为0时delete

// 等价替换例子
int main() {
shared_ptr<student> stu(new student);
shared_ptr<student> stu2 = stu;
// 释放stu的所有权,与下面一行代码等价
stu.reset();
// 创建一个智能指针右值对象, 和stu进行交换
// 交换后: 智能指针右值对象指向原stu, stu对象所有权是空指针
shared_ptr<student>().swap(stu);
// 该行结束后, 智能指针右值对象被销毁, stu2对应的计数器-1
}

[2]修改当前智能指针指向新的对象,并让原智能指针的计数器-1

等价于shared_ptr<T>(ptr).swap(*this),首先构建对象,创建智能指针管理该对象,同时将原先的智能指针-1,如果原先智能指针计数为0,则调用delete销毁

1
2
3
4
5
6
7
8
9
10
11
12
13
void reset(T* ptr);

// 等价替换例子
int main() {
shared_ptr<student> stu(new student);
shared_ptr<student> stu2 = stu;
// 让stu指向一个新的对象
stu.reset(new student);
// 创建一个智能指针右值对象, 和stu进行交换
// 交换后: 智能指针右值对象指向原stu, stu指向新创建的对象
shared_ptr<student>(new student).swap(stu);
// 该行结束, 智能指针右值对象被销毁, stu2对应的计数器-1
}

针对void reset(T* ptr); 的使用案例和错误补充

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
int main() {
shared_ptr<student> otherStu(new student);
// otherStu原先管理的对象计数器-1, 原对象被销毁
// 同时otherStu管理新的student对象
otherStu.reset<student>(new student);
}
int main() {
shared_ptr<student> otherStu(new student);
shared_ptr<student> stu1(new student);
shared_ptr<student> stu2;
stu2 = stu1;
/* otherStu 计数器为1
* stu1 计数器为2
* stu2 计数器为2 */

// ***错误用法***
stu2.reset<student>(otherStu.get());
/* otherStu 计数器为1
* stu1 计数器为1
* stu2 计数器为1 */

// 该情况会让stu2对应的引用计数器-1
// 并让stu2作为一个新的智能指针管理otherStu.get()对象
// 这并不会让otherStu的计数增加, 导致stu2和otherStu共同管理同一个对象
// 导致问题: 明明只有2个对象, 但有3个智能指针, 最后销毁时会重复销毁
}

线程安全

只保证引用计数的内存安全,不保证所指对象的成员或方法线程安全。

  • shared_ptr本身的操作是线程安全的,在修改引用次数的时候是原子操作,多线程中可以安全的复制指针或者销毁指针
  • shared_ptr所指对象的操作不是线程安全的,对对象进行操作需要加锁等安全机制