Effective STL学习笔记-条款33

来源:互联网 发布:淘宝买的lol号安全吗 编辑:程序博客网 时间:2024/06/07 05:03

提防在指针容器上使用类似remove的算法

假如有一个Widget类型,当它符合某一标准之后(处理完毕之后)我们准备从容器中删除,并且会每隔一段时间进行一次,类如下:

class Widget{public:    Widget(bool flag) : m_bIsOk(flag) {}    bool isOk()    {        return m_bIsOk;    }private:    bool m_bIsOk;};

我们默认构造一些值,并模拟从中删除元素:

    vector<Widget*> vec = {         new Widget(false),        new Widget(false),        new Widget(true),        new Widget(false),        new Widget(true),        new Widget(false),    };    cout << "vec size:" << vec.size() << endl;    vec.erase(std::remove_if(vec.begin(), vec.end(),         std::not1(mem_fn(&Widget::isOk))), vec.end());    cout << "vec size:" << vec.size() << endl;

可以预见正常打印是size=6,和size = 4。但是这其中有一个隐含的问题,那就是我们看似正常删除了指针,但是忘记删除指针对应的内容!
所以正确的做法如下:

class Widget{public:    Widget(bool flag) : m_bIsOk(flag) {}    bool isOk()    {        return m_bIsOk;    }    ~Widget() //析构函数的打印不可以帮助我们定位    {        cout << "Release Widget" << endl;    }private:    bool m_bIsOk = false;};    vec.erase(std::remove_if(vec.begin(), vec.end(), [](Widget* pWidget)    {        bool flag = pWidget->isOk();        if (flag) //释放资源        {            delete pWidget;            pWidget = nullptr;        }        return flag;    }), vec.end());

打印如下:
这里写图片描述

当然为了避免释放问题我们可以使用引用计数型智能指针,比如:
vector<std::shared_ptr<Widget>> vec

其他内容

在本节使用到的std的一些函数做一些详细的讲解:

  • mem_fn
    函数模板std::mem_fn为指向成员的指针生成包装对象,这些指针可以存储,复制和调用指向成员的指针。当调用一个对象时,可以使用引用和指针(包括智能指针)。
//c++ 11 例子class Foo{public:    void display()    {        cout << "hello world" << endl;    }    int data = 100;};//c++ 14 例子class X{public:    int x;    int &value() { return x; }    int &get() { return x; }    const int &get() const { return x; }};    // c++ 11  beign    Foo f;    auto display = std::mem_fn(&Foo::display);    display(f);    auto data = std::mem_fn(&Foo::data);    cout << data(f) << endl;    // c++ 11   end    // c++14 beign    auto a = std::mem_fn(&X::value);    auto b = std::mem_fn<int&()>(&X::get);    auto c = std::mem_fn<const int&() const>(&X::get);    auto d = [](X& x) {return x.get(); };    X x = { 11 };    cout << "a:" << a(x) << endl;    cout << "b:" << b(x) << endl;    cout << "c:" << c(x) << endl;    cout << "d:" << d(x) << endl;    // c++ 14 end

打印如下:
这里写图片描述
当我们使用std算法来调用某些类的函数或者成员,都可以使用这种方式。理解起来也比较容易,使用很方便。

原创粉丝点击