智能指针引用计数变化学习
1.引用和拷贝智能指针对象时
引用类型不增加智能指针的引用计数,拷贝会增加引用计数。
int main() { shared_ptr<Person> p=make_shared<Person>(); p->age = 5; cout<<"age: "<<p->age<<", use: "<<p.use_count()<<"\n\n"; cout<<"after B. age: "<<p->age<<", use: "<<p.use_count(); auto & p2 = p; // 引用类型,不改变引用计数 cout<<"user_count: "<<p.use_count()<<", "<<p2.use_count()<<"\n"; p2->age = 10;// 更改对象值 cout<<"age: "<<p->age<<", "<<p2->age<<"\n\n"; auto p3 = p; // 拷贝一个对象,增加引用计数 cout<<"user_count: "<<p.use_count()<<", "<<p2.use_count()<<", "<<p3.use_count()<<"\n"; p3->age = 15;// 更改对象值 cout<<"age: "<<p->age<<", "<<p2->age<<", "<<p3->age; cout<<endl; return 0; } // 运行结果: age: 5, use: 1 after B. age: 5, use: 1user_count: 1, 1 age: 10, 10 user_count: 2, 2, 2 age: 15, 15, 15
2.智能指针作为函数传参值和引用时
// 值传递,仍然会改变函数外层指向对象的值,因为指向的是同一块内存地址。产生拷贝增加引用计数 void changeValueA(shared_ptr<Person> p){ p->age = 10; cout<<"In A. age: "<<p->age<<", use: "<<p.use_count()<<"\n";// 引用计数+1,仍指向原来的对象地址 } // 引用类型,不增加引用计数 void changeValueB(shared_ptr<Person>& p){ p->age = 15; cout<<"In B. age: "<<p->age<<", use: "<<p.use_count()<<"\n"; } int main() { shared_ptr<Person> p=make_shared<Person>(); p->age = 5; cout<<"age: "<<p->age<<", use: "<<p.use_count()<<"\n\n"; changeValueA(p); cout<<"after A. age: "<<p->age<<", use: "<<p.use_count()<<"\n\n"; changeValueB(p); cout<<"after B. age: "<<p->age<<", use: "<<p.use_count(); cout<<endl; return 0; } // 运行结果 age: 5, use: 1 In A. age: 10, use: 2 after A. age: 10, use: 1 In B. age: 15, use: 1 after B. age: 15, use: 1
2.1 指针悬荡问题
void processSharedPtr(const std::shared_ptr<int>& sp) { std::cout << "Inside processSharedPtr: " << *sp << std::endl; } void processWeakPtr(const std::weak_ptr<int>& wp) { if (auto sp = wp.lock()) { // 检查对象是否仍然存在 std::cout << "Inside processWeakPtr: " << *sp << std::endl; } else { std::cout << "Inside processWeakPtr: Object no longer exists" << std::endl; } } int main() { std::shared_ptr<int> sp; { std::shared_ptr<int> temp_sp = std::make_shared<int>(100); sp = temp_sp; // sp now shares ownership with temp_sp cout<<sp.use_count()<<"\n"; } // temp_sp goes out of scope and is destroyed, but sp keeps the managed object alive processSharedPtr(sp); // Safe, sp is still valid // Now demonstrate dangling reference: const std::shared_ptr<int>& dangling_ref = sp; // Create a reference to sp sp = std::make_shared<int>(99); cout<<sp.use_count()<<" "<<dangling_ref.use_count()<<"\n"; std::weak_ptr<int> weak_ref = sp; // 使用 weak_ptr 创建引用 // 这里sp reset之后就会导致dangling_ref指向的指针已经被释放掉 sp.reset(); // sp is reset and the managed object is deallocated processWeakPtr(weak_ref); // 使用 weak_ptr 检查对象是否存在 return 0; } // 运行结果输出 2 Inside processSharedPtr: 100 1 1 Inside processWeakPtr: Object no longer exists
3.在赋值时会自动释放原来管理的对象
struct Person{ Person(uint32_t a):age(a){cout<<"create person "<<age<<endl;} ~Person(){cout<<"destruct person "<<age<<endl;} uint32_t age; }; int main() { { std::shared_ptr<Person> p1= std::make_shared<Person>(8); std::shared_ptr<Person> p2= std::make_shared<Person>(10); p1=p2; cout<<"-----"<<endl; } cout<<"out"; cout<<endl; return 0; } // 运行结果输出 create person 8 create person 10 destruct person 8 ----- destruct person 10 out
8的销毁在---之前,说明是赋值时发生的,8的引用计数会变为0,所以释放掉了。
3.1 类管理的case
struct Person{ Person(uint32_t a):age(a){cout<<"create person "<<age<<endl;} ~Person(){cout<<"destruct person "<<age<<endl;} uint32_t age; }; typedef map<uint32_t,shared_ptr<Person>> PersonMap; class PeoPleInfo{ map<uint32_t,shared_ptr<Person>> m_infos; public: void setTestData(){ m_infos[0]=make_shared<Person>(0);// 数据成员指向了3个对象 m_infos[1]=make_shared<Person>(1); m_infos[2]=make_shared<Person>(2); } void getAllInfo(PersonMap& ptr){ ptr = m_infos; } void swapData(){ PersonMap temp; temp[3] = make_shared<Person>(3); m_infos.swap(temp); } }; int main() { PeoPleInfo peo; peo.setTestData(); { PersonMap personMap; peo.getAllInfo(personMap); cout<<personMap.size()<<endl; peo.swapData(); }// personMap生命周期结束,所以原来的3个对象引用计数为0,依次释放掉了 cout<<"-----"; cout<<endl; return 0; } // 运行结果输出 create person 0 create person 1 create person 2 3 create person 3 destruct person 2 destruct person 1 destruct person 0 ----- destruct person 3
程序结束后person3没有对象指向,智能指针也会释放。
4.不能指向栈对象
struct Person{ Person(uint32_t a):age(a){cout<<"create person "<<age<<endl;} ~Person(){cout<<"destruct person "<<age<<endl;} uint32_t age; }; int main(){ { std::shared_ptr<Person> p =std::make_shared<Person>(1); Person p1(8); p.reset(&p1);// 指向了栈对象,会调用delete,但栈对象本身已经释放。 } cout<<"out"; return 0; } // 运行代码后会coredump