Objetos de enlace y función de C++

Objetos de enlace y función de C++

Introducción

Carpetas en C++ STL

  • bind1st: la primera variable de parámetro formal de operator() vincula un cierto valor.
  • bind2nd: la segunda variable de parámetro formal de operator() vincula un cierto valor.

Biblioteca C++ Boost

La biblioteca C++ Boost presenta los mecanismos de objeto de función bindy de enlace .function

expresión lambda

lambdaLas expresiones se implementan mediante mecanismos subyacentes que se basan en objetos de función.

Carpetas en C++ STL

Conociendo band1st y band2nd

band1st y band2nd son en sí mismos objetos de función.

Convierta el objeto de función binaria incorporado en STL en un objeto de función unario para su 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 y find_if usted mismo

#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;
}

función de enlace

El resultado de retorno del bind binder en C++11 sigue siendo un objeto de función.

Conozca la función de vinculación

#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;
}

enlace y función combinados con subprocesos múltiples

#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;
}

El código imprime los resultados. Debido a que tiene varios subprocesos, los resultados de la impresión no funcionan.

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

expresiones lambda en C++

La principal desventaja de los objetos de función: primero debe definir la función e inicializar el objeto de función antes de que pueda usarse.

Las expresiones lambda en C++11 se utilizan para definir y crear objetos de función anónimos para simplificar la programación.

La sintaxis de Lambda es la siguiente:

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

Lambda se divide principalmente en cinco partes, correspondientes a:

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

Se puede omitir en la expresión lambda anterior ->.

La lista de captura es la parte más interesante de las expresiones Lambda, aquí nos centraremos en la lista de captura.

La lista de captura se utiliza para describir el modo de acceso de las variables externas. El especificador del modo de acceso de la variable externa puede ser = o &, lo que indica si las variables utilizadas en el cuerpo de la función y definidas fuera pueden cambiarse en el cuerpo de la función. = indica que se pasa el valor y no se permite ningún cambio. & significa pasar por referencia, permitiendo cambios.

Incluyendo los siguientes formularios:

1. [ ] significa que no se captura ninguna variable
2. [=] significa que el método pasado por valor captura todas las variables en el ámbito principal 3. [
&] significa que el método pasado por referencia captura todas las variables en el ámbito principal 4. [ =, &
a] significa que el método pasado por valor captura todas las variables en el ámbito principal, pero el método pasado por referencia captura la variable a 5. [&, a] significa que el método pasado por referencia captura todas las variables en el ámbito principal, pero el método pasado por valor captura la variable a 6. [esto] captura puntero
externo

Para obtener más información sobre las expresiones lambda, consulte Expresiones lambda en C++ .

mutableAgregar antes del tipo de retorno de la expresión lambda puede modificar el valor de la variable pasada por valor en forma de transferencia de valor.

Objetos de función en C++

functionEl rol de es: enlazador, objeto de función, expresión lambda, solo se pueden usar en una instrucción.

Conociendo la función

#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;
}

Función de implementación personalizada

En esencia, es implementar una clase, y la función de usar el constructor y la sobrecarga del operador () es realizar el enlace de la función.

#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;
}

Supongo que te gusta

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