Effective STL学习笔记-条款33

提防在指针容器上使用类似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算法来调用某些类的函数或者成员,都可以使用这种方式。理解起来也比较容易,使用很方便。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值