Effective STL 第7条

2022-08-22  本文已影响0人  懒生活

容器中的对象如果是指针,指针指向的资源,容器没有办法自动释放.

问题引出

容器在自己析构的时候,会把包含的对象逐个析构掉. 这样容器包含的对象占用的资源就会被正确释放. 但如果容器里面存放的是指针,普通指针并没有析构函数,那么指针指向的资源,并不能被触发进行释放.

void main()
{
  vector<Widget*> vwp;
  for(int i = 0;i<10;i++)
  {
    vwp.push_back(new Widget);
  }
}

当main函数执行完毕的时候,就有10个new的Widget对象泄露.

粗陋的解决方法

在使用完vwp容器之后,对容器内的指针手动释放一次

for(auto it=vwp.begin();it!=vwp.end();it++)
  delete *it;

用for_each 取代for循环

使用for_each的好处,相对于手写for循环, for_each把事情拆分成了两部分,一部分是遍历元素,一部分是每个元素要执行的动作. 更易于理解. 针对上述的delete代码,可以参考下面的代码使用for_each修改

void delSrc(char *pSrc)
{
    delete[] pSrc;
}

int main()
{
    vector<char*> vecCharSrc;
    for (int i = 1; i <= 10; i++)
    {
        char* pChar = new char[i];
        vecCharSrc.push_back(pChar);
    }

    std::for_each(vecCharSrc.begin(), vecCharSrc.end(), delSrc);
}

避免手动释放,利用带计数的智能指针

void delSrc(char *pSrc)
{
    delete[] pSrc;
}

int main()
{

    vector<std::shared_ptr<char>> vecCharSrc;
    for (int i = 1; i <= 10; i++)
    {
        std::shared_ptr<char> pSrc(new char[i], delSrc);
        vecCharSrc.push_back(pSrc);
    }
}

利用shared_ptr 封装new出来的资源,具有自动释放的能力,比手动写释放资源代码更安全. 即使发生异常,也不会泄露,因为异常会触发各自的析构函数,而shared_ptr对象的析构函数会自动去调用delSrc函数完成资源释放.
注意,虽然auto_ptr一样有自动的资源释放能力,但是auto_ptr没有计数能力,放到容器里,极易引起误用. 请参考第八条.

上一篇 下一篇

猜你喜欢

热点阅读