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 bind
o fichário e function
os mecanismos de objeto de função.
expressão lambda
lambda
As 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++ .
mutable
Adicionar 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++
function
O 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;
}