别名构造函数,sp也成了sp2的共享对象的拥有者,但sp却指向ptr
shared_ptr<T> sp(sp2,ptr);
在讲解别名构造函数前,了解一下shared_ptr的机制
shared_ptr由两个指针构成, 为便于描述,简称其中一个是 控制块指针,另一个是存储指针。当引用计数为0时,会释放控制块指针指向的堆区内存,但不会释放存储指针指向的堆区内存.。一般情况下,控制块指针和存储指针指向的是同一块堆区内存(刚刚说明的机制恰好能够保证同一块堆区内存不会被多次释放)。
class Person {
public:
Person(int n):name(n){}
~Person() {
cout << “Person的析构 ”<<name << endl;
}
int name;
};
int main() {
//第一部分
shared_ptr<Person> sp1{ new Person(5) };//sp1是共享对象(也就是new出来的Person)的唯一拥有者
shared_ptr<Person> sp2{ sp1,new Person(6) };//现在sp1,sp2都是共享对象的拥有者
cout << sp1.use_count() <<", "<< sp2.use_count()<< endl; //2,2
//请注意:调用sp1.use_count,如果sp1不拥有任何共享对象,返回0。
//如果拥有共享对象,返回的是该共享对象的拥有者的总数
//第二部分
sp1.reset(); //reset会让sp1放弃对共享对象的所有权并重新初始化,sp1的控制区指针被置空。
//现在sp2成了共享对象的唯一拥有者
cout << sp1.use_count() << ", " << sp2.use_count() << endl; //0,1
shared_ptr<Person> sp3{ sp1,new Person(7) };//因为sp1已经不拥有任何共享对象,导致sp3也没有
cout << sp3.use_count() << endl; //0
cout << sp1.use_count() << ", " << sp2.use_count() << endl;//0,1
if (sp3.get() == nullptr) //因为get返回的是存储指针,所以这里为false
cout << "sp3的存储指针已置空" << endl;
//第三部分
sp3.reset();
if (sp3.get() == nullptr) //为true,说明reset不仅能够置空控制区指针
//还可以置空存储指针
cout << "sp3的存储指针已置空" << endl;
return 0;
}//结尾输出: Person的析构 5
//注:当共享对象的唯一拥有者sp2销毁时,引用计数由1变为0(即共享对象现在没有任何人拥有它了),
//进而调用Person的析构函数
根据结果可知:new Person(6)、new Person(7)所创建的堆区空间,都没有被释放,造成内存泄漏。