C++ 之使用标准库函数对象和函数适配器

本文通过C++ Primer 习题14.37探讨了如何使用标准库函数对象和函数适配器。强调了for_each算法不适用于改变序列的情况,因为它忽略返回值,而std::multiplies会返回结果。为实现将所有值乘以2,推荐使用std::transform,它可以保存运算结果并达到预期效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++ Primer 习题14.37

使用标准库函数对象和函数适配器,定义一个对象用于能:

1. 检查大于1024的所有值;

2. 查找不等于pooh 的所有字符串

3. 将所有值乘以2


#include <iostream>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <list>
#include <string>
#include <vector>
#include <set>
#include<utility>



bool GT6(const std::string &s)
{
    return s.size() >6;
}



class GT_cls
{
    public:
      GT_cls(std::size_t val = 0):bound(val) {}
      bool operator() (const std::string & s) { return s.size() >= bound;}
    private:
      std::string::size_type bound;
};


class equal_cls
{
    public:
        equal_cls(int i = 0):val(i) {}
        bool operator() (const int & i ) { return  i==val; }
    private:
       int val;
};




//test code
int main()
{

    std::vector<std::string> words;
    std::string word;
    while(std::cin>>word)
    {
        words.push_back(word);
    }

    std::vector<std::string>::size_type wc = std::count_if(words.begin(),words.end(),GT6);
    std::cout<<wc<<std::endl;

    std::vector<std::string>::size_type wc1 = std::count_if(words.begin(),words.end(),GT_cls(6));
    std::cout<<wc1<<std::endl;

    std::vector<std::string>::size_type wc2 = std::count_if(words.begin(),words.end(),GT_cls(2));
    std::cout<<wc2<<std::endl;

    std::vector<std::string>::iterator i = std::find_if(words.begin(), words.end(),GT_cls(2));
    std::cout<<*i<<std::endl;



    //test equal_cls
    std::vector<int> ivec(10);
    std::vector<int>::size_type cn = std::count_if(ivec.begin(), ivec.end(),equal_cls());
    std::cout<<cn<<std::endl;
    std::vector<int>::size_type cn1 = std::count_if(ivec.begin(),ivec.end(),equal_cls(10));
    std::cout<<cn1<<std::endl;
    
    
    
    //use std::functional  and function adapter
    
    
    std::vector<int> ivec;
    ivec.reserve(1030);
    for(int i = 0 ; i <1030 ;++i)
    {
        ivec.push_back(i);
    }


    //find all value that is greater than 1024
    std::vector<int>::iterator result = std::find_if(ivec.begin() ,  ivec.end() , std::bind2nd(std::greater<int>() ,1024) );

    while(result != ivec.end())
    {
        std::cout<<*result<<std::endl;
        result = std::find_if( ++result ,  ivec.end() , std::bind2nd(std::greater<int>() ,1024) );
    }



    std::vector<std::string> svec;
    svec.push_back("hello world");
    svec.push_back("test");
    svec.push_back("huqijun");
    svec.push_back("pooh");

    //find all value that is not equal to "pooh"
    std::vector<std::string>::iterator ret = std::find_if(svec.begin(),svec.end(),std::bind2nd(std::not_equal_to<std::string>(),"pooh") );
    while(ret != svec.end())
    {
        std::cout<<*ret<<std::endl;
        ret = std::find_if(++ret,svec.end(),std::bind2nd(std::not_equal_to<std::string>(),"pooh") );
    }


    //double every value
    std::vector<int> ivec2;
    ivec2.reserve(12);
    for(int i = 0; i<12 ; ++i)
    {
        ivec2.push_back(i);
    }

<span style="background-color: rgb(255, 0, 0);">    std::for_each(ivec2.begin(),ivec2.end(),std::bind2nd(std::multiplies<int>(),2) );

    for(std::vector<int>::iterator i = ivec2.begin() ;  i!= ivec2.end()  ; ++i)
    {
        std::cout<<*i<<std::endl;
    }</span>
    
    
    
    
    
    
    return 0;

}


上面的代码,最后一段实现将所有值乘以2 是失败的,没有实现目的

原因是for_each 算法是不改变序列的算法, for_each 会忽略第三个参数函数的返回值:

UnaryFunction for_each( InputIt first, InputIt last, UnaryFunction f );
   
     

Applies the given function object f to the result of dereferencing every iterator in the range [first, last), in order.

If InputIt is a mutable iterator, f may modify the elements of the range through the dereferenced iterator. If returns a result, the result is ignored.



而std::mutiplies<int>()  就是会返回值,因为被忽略了:

constexpr T operator()(const T &lhs, const T &rhs) const 
{
    return lhs * rhs;
}


所以用for_each 和std::mutiplies 是实现不了将所有值乘2的目的


    std::transform(b.begin(),b.end(), b.begin(),std::bind2nd(std::multiplies<int>(),2) );



使用std::tranform 可以实现我们目的:

std::transform applies the given function to a range and stores the result in another range, beginning at d_first.


std::transform会见f 运算的结果保存下来,所以可以实现都乘以2的目的


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值