C++ fichário e objetos de função

C++ fichário e objetos de função

Introdução

Fichários em C++ STL

  • bind1st: A primeira variável de parâmetro formal de operator() vincula um determinado valor.
  • bind2nd: A segunda variável de parâmetro formal de operator() vincula um determinado valor.

Biblioteca C++ Boost

A biblioteca C++ Boost apresenta bindo fichário e functionos mecanismos de objeto de função.

expressão lambda

lambdaAs expressões são implementadas por mecanismos subjacentes que dependem de objetos de função.

Fichários em C++ STL

Conhecendo o band1st e o band2nd

band1st e band2nd são eles próprios objetos de função.

Converta o objeto de função binária integrado em STL em um objeto de função unário para uso.

#include<iostream>
#include<functional>
#include<vector>
#include<algorithm>
#include<time.h>

using namespace std;

template<typename Container>
void showContainer(Container &con){
    
    
    //由于编译的原因,所以需要加上typename,防止无法识别Container类型
    typename Container::iterator it = con.begin();
    for (; it != con.end();it++)
    {
    
    
        cout << *it << " ";
    }
    cout << endl;
}

int main(){
    
    
    vector<int> vec;
    srand(time(nullptr));
    for (int i = 0; i < 20;i++)
    {
    
    
        //产生1~100之间的随机数
        vec.push_back(rand() % 100 + 1);
    }

    showContainer(vec);
    sort(vec.begin(), vec.end());
    showContainer(vec);

    // greater二元函数对象,用于从大到小排序
    sort(vec.begin(), vec.end(), greater<int>());
    showContainer(vec);

    // bind1st和bind2nd可以将二元函数对象转化为一元函数对象,也就是说传入的默认值对应二元函数对象的形参
    // 寻找第一个小于70的索引,原序列按照从大到小排序 return 70>*it 
    // auto it = find_if(vec.begin(), vec.end(), bind1st(greater<int>(), 70));
    // 寻找第一个小于70的索引,原序列按照从大到小排序 return *it<70
    auto it = find_if(vec.begin(), vec.end(), bind2nd(less<int>(), 70));

    if(it!=vec.end())
    {
    
    
        vec.insert(it, 70);
    }
    showContainer(vec);
    return 0;
}

Implemente band1st e find_if você mesmo

#include<iostream>
#include<functional>
#include<vector>
#include<algorithm>
#include<time.h>

using namespace std;

template<typename Container>
void showContainer(Container &con){
    
    
    //由于编译的原因,所以需要加上typename,防止无法识别Container类型
    typename Container::iterator it = con.begin();
    for (; it != con.end();it++)
    {
    
    
        cout << *it << " ";
    }
    cout << endl;
}
template <typename Compare, typename T>
class _mybind1st{
    
    
    public:
    _mybind1st(Compare comp,T val):
        _comp(comp),_val(val){
    
    }

    bool operator()(const T &second){
    
    
        return _comp(_val, second);
    }
    private:
        Compare _comp;
        T _val;
};

template <typename Compare, typename T>
_mybind1st<Compare, T> mybind1st(Compare comp, const T &val)
{
    
    
    return _mybind1st<Compare, T>(comp, val);
}

template<typename Iterator,typename Compare>
Iterator my_find_if(Iterator first,Iterator last,Compare comp){
    
    
    for (; first != last;first++){
    
    
        //comp.operator()(*first)
        if(comp(*first)){
    
    
            return first;
        }
    }
    return last;
}

int main(){
    
    
    vector<int> vec;
    srand(time(nullptr));
    for (int i = 0; i < 20;i++)
    {
    
    
        //产生1~100之间的随机数
        vec.push_back(rand() % 100 + 1);
    }

    showContainer(vec);
    sort(vec.begin(), vec.end());
    showContainer(vec);

    // greater二元函数对象,用于从大到小排序
    sort(vec.begin(), vec.end(), greater<int>());
    showContainer(vec);

    auto it = my_find_if(vec.begin(), vec.end(), mybind1st(greater<int>(), 70));
    // auto it = my_find_if(vec.begin(), vec.end(), bind2nd(less<int>(), 70));

    if(it!=vec.end())
    {
    
    
        vec.insert(it, 70);
    }
    showContainer(vec);
    return 0;
}

função de ligação

O resultado de retorno do fichário de ligação em C++11 ainda é um objeto de função.

Conheça a função de ligação

#include<iostream>
#include<string>
#include<functional>

using namespace std;

void hello(string str)
{
    
    
    cout << str << endl;
}

int sum(int a,int b)
{
    
    
    return a + b;
}

class Test
{
    
    
    public:
    int sum(int a,int b)
    {
    
    
        return a + b;
    }
};

int main(){
    
    
    // bind是函数模板,可以自动推演模板类型参数,第一个参数是函数的指针
    bind(hello, "hello,world")(); 
    cout << bind(sum, 10, 20)() << endl;
    //bind使用函数对象的时候,必须要利用函数对象才能使用
    cout << bind(&Test::sum, Test(), 10, 20)()<<endl;

    // placeholders是占位符
    bind(hello, placeholders::_1)("hello,bind2!");
    bind(sum, placeholders::_1, placeholders::_2)(1, 3);

    function<void(string)> func1 = bind(hello, placeholders::_1);
    func1("hello,china!");
    func1("hello,shanghai!");
    return 0;
}

ligação e função combinadas com multithreading

#include<iostream>
#include<string>
#include<thread>
#include<vector>
#include<functional>

using namespace std;

class Thread{
    
    
    public:
        Thread(function<void()> func) : _func(func){
    
    };
        thread start()
        {
    
    
            thread t(_func);
            return t;
        }
    private:
        function<void()> _func;
};

class ThreadPool
{
    
    
    public:
        ThreadPool(){
    
    };
        ~ThreadPool(){
    
    
            for (int i = 0;i<_pool.size();i++)
            {
    
    
                delete _pool[i];
            }
        };
        void startPool(int size)
        {
    
    
            for (int i = 0; i < size; i++)
            {
    
    
                _pool.push_back(new Thread(bind(&ThreadPool::runThread,this,i)));
            }
            for (int i = 0; i < size; i++)
            {
    
    
                _handler.push_back(_pool[i] -> start());
            }
            for (int i = 0; i < size;i++)
            {
    
    
                _handler[i].join();
            }
        }
    private:
        vector<Thread*> _pool;
        vector<thread> _handler;
        void runThread(int id)
        {
    
    
            cout << "call run Thread id :" << id << endl;
        }
};

int main()
{
    
    
        ThreadPool pool;
        pool.startPool(10);
        return 0;
}

O código imprime os resultados. Como é multithread, os resultados da impressão estão fora de ordem.

call run Thread id :call run Thread id :call run Thread id :2call run Thread id :5
call run Thread id :61
call run Thread id :9
call run Thread id :4

call run Thread id :8
0
call run Thread id :
call run Thread id :37

expressões lambda em C++

A principal desvantagem dos objetos de função: você precisa definir a função primeiro e inicializar o objeto de função antes de poder ser usado.

As expressões lambda em C++11 são usadas para definir e criar objetos de função anônimos para simplificar a programação.

A sintaxe do Lambda é a seguinte:

[captures](params) -> return_type {
    
     body };

Lambda é dividido principalmente em cinco partes, correspondendo a:

[捕获列表] (函数参数) mutable 或 exception 声明 -> 返回值类型 {函数体}

Pode ser omitido na expressão lambda acima ->.

A lista de captura é a parte mais interessante das expressões Lambda. Aqui vamos nos concentrar na lista de captura.

A lista de captura é usada para descrever o modo de acesso das variáveis ​​externas.O especificador do modo de acesso da variável externa pode ser = ou &, indicando se as variáveis ​​usadas no corpo da função e definidas fora podem ser alteradas no corpo da função. = indica que o valor foi passado e nenhuma alteração é permitida. & significa passar por referência, permitindo alterações.

Incluindo os seguintes formulários:

1. [ ] significa que nenhuma variável é capturada
2. [=] significa que o método passado por valor captura todas as variáveis ​​no escopo pai 3. [
&] significa que o método passado por referência captura todas as variáveis ​​no escopo pai 4. [ =,
&a] significa que o método passado por valor captura todas as variáveis ​​no escopo pai, mas o método passado por referência captura a variável a 5. [&, a] significa que o método passado por referência captura todas as variáveis ​​no escopo pai, mas o método passado por valor captura a variável a 6. [este] captura ponteiro
externo

Para obter mais informações sobre expressões lambda, consulte Expressões lambda em C++ .

mutableAdicionar antes do tipo de retorno da expressão lambda pode modificar o valor da variável passada por valor na forma de transferência de valor.

Objetos de função em C++

functionO papel de é: fichário, objeto de função, expressão lambda, eles só podem ser usados ​​em uma instrução.

Conhecendo a função

#include<iostream>
#include<string>
#include<algorithm>
#include<functional>
#include<ctime>

using namespace std;

void hello1()
{
    
    
    cout << "hello,world!" << endl;
}
void hello2(string str)
{
    
    
    cout << str << endl;
}
int sum(int a,int b){
    
    
    return a + b;
}

class Test{
    
    
    public:
    void hello(string str){
    
    
        cout << str;
    }
};

int main(){
    
    

    /* 
    function函数的使用方法,function<typename(typename1,...)> xxx=yyy;
    typename表示函数的返回类型,typename_1表示寒暑的参数类型,xxx表示function重命名的函数,yyy表示原来的函数
    */
    //  调用函数hello1(),function使用的是函数类型
    function<void()> func1 = hello1;
    // 调用函数hello1(),function使用的是函数指针类型
    // function<void(*)> func1 = hello1;
    // 本质上和hello1()没有区别,调用了func1对象()重载函数->hello1.operator()
    func1();

    function<void(string)> func2 = hello2;
    func2("hello2!");

    function<int(int, int)> func3 = sum;
    cout << func3(10, 20) << endl;

    function<int(int, int)> func4 = [](int a, int b)->int{
    
     return a + b; };
    cout << func4(10, 20);

    function<void(Test*, string)> func5 = &Test::hello;
    func5(&Test(), "call Test::hello!");

    return 0;
}

Função de implementação personalizada

Em essência, é para implementar uma classe, e a função de usar construtor e sobrecarga de operador () é realizar a ligação de função.

#include<iostream>
#include<functional>
#include<string>

using namespace std;

void hello(string str)
{
    
    
    cout << str << endl;
}

int sum(int a,int b)
{
    
    
    return a + b;
}

template<typename Fty>
class myfunction{
    
    
};

/*
template<typename R,typename A1>
class myfunction<R(A1)>
{
    public:
        //函数返回的指针参数类型
        using PFUNC = R (*)(A1);
        myfunction(PFUNC pfunc) : _pfunc(pfunc){};
        R operator()(A1 arg){
            return _pfunc(arg);
        }
    private:
    PFUNC _pfunc;
};

template <typename R, typename A1,typename A2>
class myfunction<R(A1,A2)>
{
public:
    // 函数返回的指针参数类型
    using PFUNC = R (*)(A1,A2);
    myfunction(PFUNC pfunc) : _pfunc(pfunc){};
    R operator()(A1 arg1,A2 arg2)
    {
            return _pfunc(arg1,arg2);
    }

private:
    PFUNC _pfunc;
};
*/
// ...表示可变参数类型个数,和上面两个类的功能是一样的
template <typename R, typename... A>
class myfunction<R(A...)>
{
    
    
public:
    // 函数返回类型的指针,函数的参数类型列表
    using PFUNC = R (*)(A...);
    myfunction(PFUNC pfunc) : _pfunc(pfunc){
    
    };
    R operator()(A... arg)
    {
    
    
            return _pfunc(arg...);
    }

private:
    PFUNC _pfunc;
};

int main(){
    
    
    //就是构造函数重命名了hello函数
    myfunction<void(string)> func1(hello);
    func1("hello1");

    myfunction<int(int, int)> func2(sum);
    cout << func2(2, 3) << endl;

    return 0;
}

Acho que você gosta

Origin blog.csdn.net/qq_45041871/article/details/131882143
Recomendado
Clasificación