智能指针引用计数为什么不是0?

问题1:

#include<memory>
#include<cstdio>
#include<map>
using namespace std;

int main() {
    shared_ptr<int> ptr = make_shared<int>(100);
    printf("=%d,count=%ld\n", *ptr.get(), ptr.use_count());
    map<int, shared_ptr<int>> mp;
    mp.insert(pair<int, shared_ptr<int>>(1, ptr));
    mp.insert(pair<int, shared_ptr<int>>(2, ptr));
    printf("=%d,count=%ld\n", *ptr.get(), ptr.use_count());
    mp.clear();
    mp.clear();
    printf("=%d,count=%ld\n", *ptr.get(), ptr.use_count());
    return 0;
}

输出:
=100,count=1
=100,count=3
=100,count=1 // 为什么这里引用计数是1而不是0呢?

问题2:

#include<memory>
#include<cstdio>
#include<map>
using namespace std;

int main() {
    shared_ptr<int> ptr = make_shared<int>(100);
    printf("=%d,count=%ld\n", *ptr.get(), ptr.use_count());
    map<int, shared_ptr<int>> mp;
    mp.insert(pair<int, shared_ptr<int>>(1, ptr));
    mp.insert(pair<int, shared_ptr<int>>(2, ptr));
    printf("=%d,count=%ld\n", *ptr.get(), ptr.use_count());
    ptr.reset();
    printf("count=%ld\n", ptr.use_count());
    return 0;
}

输出:
=100,count=1
=100,count=3
count=0 //这里为什么是0而不是2呢? 一直理解的 reset()是引用计数减1.

阅读 3.2k
3 个回答

问题1:
ptr 还在,还有一个引用。

问题2:
reset 之后,ptr 的指向改变,引用计数已经不是原来指针的引用计数了。新指针是个 nullptr ,引用计数为 0 。原来的指针引用计数是 2 ,两个引用都在 map 里,已经无法通过 ptr 访问。

对于问题 1 中的第三次输出,ptr 没有释放,因此还有 1 个引用计数占用,打印 1.
对于问题 2 中的第三次输出,是 ptr 这个共享指针本身释放,而非资源释放,因此 ptr.use_count() 打印 0. 可以运行下面代码验证:

#include<memory>
#include<cstdio>
#include<map>
using namespace std;

int main() {
    shared_ptr<int> ptr = make_shared<int>(100);
    printf("=%d,count=%ld\n", *ptr.get(), ptr.use_count());
    map<int, shared_ptr<int>> mp;
    mp.insert(pair<int, shared_ptr<int>>(1, ptr));
    mp.insert(pair<int, shared_ptr<int>>(2, ptr));

    printf("=%d,count=%ld\n", *ptr.get(), ptr.use_count());
    ptr.reset();
    printf("count=%ld\n", ptr.use_count());

    printf("=%d,count=%ld\n", *mp[1].get(), mp[1].use_count());
    printf("=%d,count=%ld\n", *mp[2].get(), mp[2].use_count());

    return 0;
}

输出:

=100,count=1
=100,count=3
count=0
=100,count=2
=100,count=2

你可以设想一下这个函数的逻辑

    void reset() _NOEXCEPT
    {
        shared_ptr().swap(*this);
    }

第一步, 创造一个空shared_ptr对象,与原智能指针交换.交换后指向nullptr,引用为0;
第二步, 原始的指针成了右值, 在语句调用结束消灭, 随即, 原资源引用数减一, 如减为0, 自行消灭,否则继续留存.

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏