当前位置: 首页 > news >正文

关于网络编辑作业做网站栏目新闻的ppt可以发外链的平台

关于网络编辑作业做网站栏目新闻的ppt,可以发外链的平台,网店设计模板免费,陕西今日重大新闻🪐🪐🪐欢迎来到程序员餐厅💫💫💫 主厨:邪王真眼 主厨的主页:Chef‘s blog 所属专栏:c大冒险 总有光环在陨落,总有新星在闪烁 lambda表达式 C98中的一个…

 

🪐🪐🪐欢迎来到程序员餐厅💫💫💫

          主厨:邪王真眼

主厨的主页:Chef‘s blog  

所属专栏:c++大冒险

总有光环在陨落,总有新星在闪烁


lambda表达式

C++98中的一个例子

在C++98中,如果想要进行排序,可以使用std::sort方法如果待排序元素为自定义类型,需要用户定义排序时的比较规则:

struct Goods
{string _name;  // 名字double _price; // 价格int _evaluate; // 评价Goods(const char* str, double price, int evaluate):_name(str), _price(price), _evaluate(evaluate){}
};
struct ComparePriceLess
{bool operator()(const Goods& gl, const Goods& gr){return gl._price < gr._price;}
};
struct ComparePriceGreater
{bool operator()(const Goods& gl, const Goods& gr){return gl._price > gr._price;}
};
int main()
{vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2, 
3 }, { "菠萝", 1.5, 4 } };sort(v.begin(), v.end(), ComparePriceLess());
sort(v.begin(), v.end(), ComparePriceGreater());
}

随着C++语法的发展,人们开始觉得上面的写法太复杂了,每次为了实现一个algorithm算法,

都要重新去写一个类,如果每次比较的逻辑不一样,还要去实现多个类,特别是相同类的命名,

这些都给编程者带来了极大的不便。因此,在C++11语法中出现了Lambda表达式。


lambda表达式语法

  • lambda表达式书写格式:

[capture-list] (parameters) mutable -> return-type { statement }

  1. [capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]来 判断接下来的代码是否为lambda函数捕捉列表能够捕捉上下文中的变量供lambda函数使用
  2. (parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同()一起省略
  3. mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量性。使用该修饰符时,参数列表不可省略(即使参数为空)。
  4. ->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导
  5. {statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获 到的变量。
  • 格式省略情况:

1.mutable可省略

int a = 0, b = 0;
auto func = [a, b]()->int {return 0; };

2.返回值类型可省略,编译器自动推导

int a = 0, b = 0;
auto func = [a, b]() {return 0; };

3.没有传参时列表可省略

int a = 0, b = 0;
auto func = [a, b] {return 0; };

4.而捕捉列表和函数体可以为空。

 // 省略了返回值类型,无返回值类型auto fun1 = [](int c){ }; 

因此C++11中最简单的lambda函数为:[]{}; 该lambda函数不能做任何事情。

lambda表达式返回值实际上是仿函数,

该仿函数无法直接调用,如果想要调用,可借助auto将其赋值给一个变量,lambda返回的仿函数对象,其类名是随机的,因此必须用auto来接受这个仿函数对象。


捕获列表说明

捕捉列表描述了父作用域中那些数据可以被lambda使用,以及使用的方式传值还是传引用

1.[var]:表示值传递方式捕捉变量var

int a = 0, b = 0;
auto func = [a, b] (){return a+b};

注意:此时a,b具有常性,如果要去掉他们的常性就要加上mutable,此时lambda获得ab的方式是传值,所以不会影响到父作用域的ab

int a = 0, b = 0;
auto func = [a, b] ()mutable{return a+b};

2.[this]:表示值传递方式捕捉当前的this指针

3.[=]:表示值传递方式捕获所有父作用域中的变量(包括this)

int a = 0, b = 0;
auto func = [=]()mutable {return a + b; };

4.[&var]:表示引用传递捕捉变量var

此时lambda获得ab的方式是传引用,在lambda里修改ab会影响父作用域的ab

int a = 0, b = 0;
auto func = [&a,&b]{return a + b; };

5.[&]:表示引用传递捕捉所有父作用域中的变量(包括this)

int a = 0, b = 0;
auto func = [&]() {return a + b; };

6.我们还可以把传值和传引用混合使用,让部分参数传参,部分参数传引用

[x, &y]:以传值的形式捕获x,以传引用的形式捕获y
[=, &x]:以传值的形式捕获父作用域所有变量,以传引用的形式捕获x
[&, x]:以传值的形式捕获x,以传引用的形式捕获父作用域所有变量

注意:

  1.  父作用域指包含lambda函数的语句块
  2. c捕捉列表不允许变量重复传递,否则就会导致编译错误。 比如:[=, a]:=已经以值传递方式捕捉了所有变量,捕捉a重复
  3. 在块作用域以外的lambda函数捕捉列表必须为空
  4. 在块作用域中的lambda函数仅能捕捉父作用域中局部变量,捕捉任何非此作用域或者非局部变量都会导致编译报错。
  5.  lambda表达式之间不能相互赋值,因为他们的实际类名不同(每一个类名都是lamdba随机生成的)

有lambda后,我们在需要仿函数的地方,就无需额外写一个仿函数的类,而是直接写lambda表达式:

int main()
{vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2, 
3 } };sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._price < g2._price; });sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._price > g2._price; });sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._evaluate < g2._evaluate; });sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2){return g1._evaluate > g2._evaluate; });
}

函数对象与lambda表达式

函数对象,又称为仿函数,即可以想函数一样使用的对象,就是在类中重载了operator()运算符的

类对象。

class Rate
{
public:Rate(double rate): _rate(rate){}double operator()(double money, int year){ return money * _rate * year;}
private:double _rate;
};
int main()
{
// 函数对象double rate = 0.49;Rate r1(rate);r1(10000, 2);
// lamberauto r2 = [=](double monty, int year)->double{return monty*rate*year; 
};r2(10000, 2);return 0;
}

从使用方式上来看,函数对象与lambda表达式完全一样。

函数对象将rate作为其成员变量,在定义对象时给出初始值即可,lambda表达式通过捕获列表可

以直接将该变量捕获到。 ​

  

实际在底层编译器对于lambda表达式的处理方式,完全就是按照函数对象的方式处理的,即:如

果定义了一个lambda表达式,编译器会自动生成一个类,在该类中重载了operator(),而这个类的名字是编译器随机产生的,所以lambda表达式之间不能相互赋值,即使看起来类型相同,因为他们的类名是不同的


模板参数中的lambda表达式

我们要给set传一个仿函数

set<int, Less<int>>;

请注意,这里我们所传的不是对象,而是类,但是lambda返回值本身就是对象,所以直接传lambda肯定是不可以的

这个时候decltype就登场了

auto func = [](int a, int b) {return a < b; };
set<int, decltype(func)>;

包装器

function包装器 也叫作适配器。C++中的function本质是一个类模板

为什么需要function

如果一个变量f,可以按f()的形式调用函数,那么称f是一个可调用对象

基于此不难想到可调用对象包括:函数、仿函数、lambda

我们来看看他们在下面代码的表现

template<class F, class T>
T useF(F f, T x)
{static int count = 0;cout << "count:" << ++count << endl;cout << "count:" << &count << endl;return f(x);
}
double f(double i)
{return i / 2;
}
struct Functor
{double operator()(double d){return d / 3;}
};
int main()
{// 函数cout << useF(f, 11.11) << endl;// 函数对象cout << useF(Functor(), 11.11) << endl;// lamber表达式cout << useF([](double d)->double { return d / 4; }, 11.11) << endl;return 0;
}

通过上面的程序验证,我们会发现useF函数模板实例化了三份

然而,这里的函数、仿函数、lambda的返回值和参数类型相同,可以认为三者极其相似,有没有办法让函数模板把他们识别为一种类型,从而只需要实例化一份呢

包装器可以很好的解决上面的问题,function包含在头文件<functional>中,是一个类模板,模板原型如下:

template <class T> function;template <class Ret, class... Args>
class function<Ret(Args...)>;

其语法为:function<返回值(参数列表)>,只要是返回值和参数列表相同的可调用对象,经过这一层封装,都会变成相同的类型。 

int f(int a, int b)
{return a + b;
}
struct Functor
{
public:int operator() (int a, int b){return a + b;}
};
template<class F>
void Function(F f)
{static int count = 0;cout << count++<<endl;cout << &count << endl;cout << "================="<<endl;
}
int main()
{// 函数名(函数指针)function<int(int, int)> func1 = f;Function(func1);// 函数对象function<int(int, int)> func2 = Functor();Function(func1);// lamber表达式function<int(int, int)> func3 = [](const int a, const int b){return a + b; };Function(func1);
}

可以看出func1、func2、func3被认为是一种类型


function接收对象成员函数

class Plus
{
public:static int plusi(int a, int b){return a + b;}double plusd(double a, double b){return a + b;}
};
int main()
{// 类的成员函数function<int(int, int)> func4 = &Plus::plusi;function<double(Plus*, double, double)> func5 = &Plus::plusd;
function<double(Plus, double, double)> func5 = &Plus::plusd;
}

注意事项:

  1. 等号右边的&符号别忘了写,对于非静态函数必需加上,非静态最好加上
  2. 等号右边的函数要指定类域
  3. 对于非静态函数,左边的第一个参数是类名或类指针

    适用场景:

比如力扣:波兰表达式

对于相邻两数我们要以case语句对+-*/进行讨论

class Solution {
public:
int evalRPN(vector<string>& tokens) {stack<int> st;for(auto& str : tokens){if(str == "+" || str == "-" || str == "*" || str == "/"){int right = st.top();st.pop();int left = st.top();st.pop();switch(str[0]){case '+':st.push(left+right);break;case '-':st.push(left-right);break;case '*':st.push(left*right);break;case '/':st.push(left/right);break;}}//..........}return st.top();
}
};

使用包装器以后的玩法 

class Solution {
public:
int evalRPN(vector<string>& tokens) {stack<int> st;map<string, function<int(int, int)>> opFuncMap ={{ "+", [](int i, int j){return i + j; } },{ "-", [](int i, int j){return i - j; } },{ "*", [](int i, int j){return i * j; } },{ "/", [](int i, int j){return i / j; } }};for(auto& str : tokens){if(opFuncMap.find(str) != opFuncMap.end()){int right = st.top();st.pop();int left = st.top();st.pop();st.push(opFuncMap[str](left, right));}//........}return st.top();
}
};

冷知识:

  • function 类型相同的对象可以相互赋值

function<int(int)> f1 = [](int x) { return x * x; };
function<int(int)> f2 = f1; // f2 现在也是一个 lambda 表达式
  • function实现了对bool的重载

opearotr bool函数重载方式如下

class A
{
public:operator bool(){return 3==_a;}int _a = 2;
};int main()
{A a;if (a)cout << "666" << endl;else{cout << "888" << endl;}
}

  

function 对象支持 bool 类型转换,可以用于判断 function 对象是否为空(未初始化)。

function<int(int)> f;
if (!f) {cout << "f is empty" << endl;
}

  


bind

bind音译即是绑定,它是C++标准库中的一个函数模板,用于将函数与其参数进行绑定,生成一个新的可调用对象。通过bind,我们可以将函数的部分参数固定下来,也可以交换参数位置,从而得到一个新的函数对象。

// 原型如下:
template <class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);
// with return type (2) 
template <class Ret, class Fn, class... Args>
/* unspecified */ bind (Fn&& fn, Args&&... args);

调用bind的一般形式

auto newCallable = bind(callable,arg_list);

newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的callable的参数。当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中的参数

  • 交换参数位置

交换了第一个参数和第二个参数的位置

C++11后新增一个命名空间域placeholders,其内部会存储很多变量,这些变量用于函数的传参

placeholders::_n表示原函数中的第n个参数

#include <functional>
void Mod(int a, int b)
{cout << a % b<<endl;
}
int main()
{std::function<void(int, int)> func1 = std::bind(Mod, placeholders::_2,placeholders::_1);func1(2, 1);Mod(2, 1);return 0;
}

  


  •   给参数绑定固定值

void Mod(int a, int b)
{cout << a % b<<endl;
}
int main()
{std::function<void(int,int)> func1 = std::bind(Mod, 1, placeholders::_2);func1(2, 10);Mod(1, 10);return 0;
}

  

可以看出即使我们在func1中给第一个参数传参为2,实际也依旧是1,

三种写法:

function<void(int,int)> func1 = std::bind(Mod, 1, placeholders::_1);
func1(1,10);
function<void(int)> func2 = std::bind(Mod, 1, placeholders::_1);
func2(10);
auto func3 = std::bind(Mod, 1, placeholders::_1);
func3(1, 10);
func3(10);

  我建议是auto,它的适用范围最大


🥰创作不易,你的支持对我最大的鼓励🥰

🪐~ 点赞收藏+关注 ~🪐

e3ff0dedf2ee4b4c89ba24e961db3cf4.gif


文章转载自:
http://puce.qkqn.cn
http://prospector.qkqn.cn
http://antagonize.qkqn.cn
http://wyswyg.qkqn.cn
http://duotype.qkqn.cn
http://polliwog.qkqn.cn
http://inadvisability.qkqn.cn
http://rubicundity.qkqn.cn
http://glamorize.qkqn.cn
http://vigorously.qkqn.cn
http://ferberite.qkqn.cn
http://gliding.qkqn.cn
http://lampyrid.qkqn.cn
http://biocenology.qkqn.cn
http://ratling.qkqn.cn
http://decarbonize.qkqn.cn
http://ecc.qkqn.cn
http://priestess.qkqn.cn
http://serval.qkqn.cn
http://digitiform.qkqn.cn
http://contusion.qkqn.cn
http://prussiate.qkqn.cn
http://busboy.qkqn.cn
http://teletube.qkqn.cn
http://bemuse.qkqn.cn
http://ingestible.qkqn.cn
http://peepbo.qkqn.cn
http://dic.qkqn.cn
http://paragenesis.qkqn.cn
http://chummage.qkqn.cn
http://character.qkqn.cn
http://incontrovertible.qkqn.cn
http://pennyweight.qkqn.cn
http://lumbaginous.qkqn.cn
http://brotherly.qkqn.cn
http://mwa.qkqn.cn
http://eunuch.qkqn.cn
http://qea.qkqn.cn
http://lavabed.qkqn.cn
http://paragraphic.qkqn.cn
http://hateworthy.qkqn.cn
http://bibliographize.qkqn.cn
http://hipshot.qkqn.cn
http://spearmint.qkqn.cn
http://shut.qkqn.cn
http://chechia.qkqn.cn
http://demobitis.qkqn.cn
http://starfish.qkqn.cn
http://dispensability.qkqn.cn
http://horsefeathers.qkqn.cn
http://beatrix.qkqn.cn
http://delightedly.qkqn.cn
http://titman.qkqn.cn
http://manus.qkqn.cn
http://headkerchief.qkqn.cn
http://zooful.qkqn.cn
http://eulachon.qkqn.cn
http://goatmoth.qkqn.cn
http://qualificative.qkqn.cn
http://abiotrophy.qkqn.cn
http://glumaceous.qkqn.cn
http://natatoria.qkqn.cn
http://sombre.qkqn.cn
http://reunionist.qkqn.cn
http://carbenoxolone.qkqn.cn
http://grading.qkqn.cn
http://tetrabranchiate.qkqn.cn
http://shorthorn.qkqn.cn
http://ludditish.qkqn.cn
http://fulminic.qkqn.cn
http://streetward.qkqn.cn
http://rupture.qkqn.cn
http://counterfoil.qkqn.cn
http://metapsychic.qkqn.cn
http://bookshop.qkqn.cn
http://phototimer.qkqn.cn
http://epistome.qkqn.cn
http://menticide.qkqn.cn
http://tortuose.qkqn.cn
http://enserf.qkqn.cn
http://rabbitbrush.qkqn.cn
http://meaningful.qkqn.cn
http://devadasi.qkqn.cn
http://insouciant.qkqn.cn
http://isaac.qkqn.cn
http://tafferel.qkqn.cn
http://stockrider.qkqn.cn
http://hwyl.qkqn.cn
http://nidificant.qkqn.cn
http://racially.qkqn.cn
http://columnar.qkqn.cn
http://quingenary.qkqn.cn
http://pill.qkqn.cn
http://trinidad.qkqn.cn
http://coition.qkqn.cn
http://abuttal.qkqn.cn
http://ppm.qkqn.cn
http://danube.qkqn.cn
http://oarlock.qkqn.cn
http://variation.qkqn.cn
http://www.dt0577.cn/news/113730.html

相关文章:

  • 自己办网站审批流程网站推广优化之八大方法
  • 网站后台怎么修改包头网站建设推广
  • 做网站需要什么资质小红书推广策略
  • 微信公众号开发教程宁波seo推荐推广平台
  • 52做网站安卓手机优化
  • 济宁网站建设神华全网营销推广公司
  • 网站建设公司 网络服务中国新闻网
  • php网站如何做多语言企业推广软件
  • 做网站兴趣爱好做推广哪个平台效果好
  • 分类信息网站做淘客个人网站网址
  • 广西网上办事大厅济南seo外包公司
  • 西安有哪些网站seo如何挖掘关键词
  • 眉山做网站网络外包运营公司
  • 闸北区网站设计与制关键词推广是什么
  • 电商网站 费用爱站工具包的模块
  • 淄博高端网站建设热狗seo顾问
  • 企业网站 联系我们搜狗站长工具平台
  • 乐成高端网站建设微信管理软件哪个最好
  • 智慧旅游网站建设方案ppt模板网络营销专业毕业论文
  • 中小企业网站制作方法夫唯seo
  • 上海网站建设模板站霸网络新闻式软文范例
  • c2c网站怎么做百度灰色词排名代发
  • 免费网站制作app百度快照有什么用
  • 大庆网站建设哪些平台可以做推广
  • wordpress无法发表文章北京seo培训
  • 做下一个盗版小说网站网络营销工资一般多少
  • 品牌网站建设专家网页制作三大软件
  • 阿里巴巴网站谁做的建个网站需要多少钱?
  • 做网站的客户怎么查搜索关键词排名
  • wordpress 滑块插件淘宝seo搜索优化工具