最近自己用c++写socks5服务器,中间试图用智能指针来控制client类的分配与释放。达到在连接断开时,自动释放socket等资源的目的。但是写的过程中,发现用智能指针时,要尤其注意什么时候会让智能指针的计数为0,从而出发析构函数。示例代码如下:

#include <bits/stdc++.h>
using namespace std;
class A
{
public:
    int a;
    A()
    {
        a = 3;
    }
    void remove_first(vector<shared_ptr<A>>& v)
    {
        if(v.size()>=1)
            v.erase(v.begin());
        cout<<"a = "<<a<<" from A::remove_first"<<endl;
    }
    ~A()
    {
        a = 5;
        cout<<"destructor"<<endl;
    }
};
int main()
{
    vector<shared_ptr<A>> v;
    {
        shared_ptr<A> p = make_shared<A>();
        v.push_back(p);
    }
    v.front()->remove_first(v);
    return 0;
}

可以将A看作要管理的资源,v是容器。在A::remove_first这个函数中,需要注意对v的操作可能让自己的智能指针被析构,从而导致自己被析构,类似delete this的感觉。

这段程序在gcc8编译后运行的结果是

destructor
a = 5 from A::remove_first

说明的确在执行了析构函数,并且a的值也被改变了。试试上析构以后,a的值就是未定义的了。

总结下,当用智能指针管理对象时,如果对象中涉及到对智能指针的释放,要考虑到释放的是不是自己,如果是自己,就要考虑到自己被析构以后就不能再使用任何对象成员变量了,因为析构以后这些都是未定义的了。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注