智能指针引用计数变化学习

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

 

posted @ 2024-05-30 07:43  lypbendlf  阅读(37)  评论(0编辑  收藏  举报