C++语言的lambda表达式

简介: C++从函数对象到lambda表达式以及操作参数化

函数对象(function object)是指一个类重载函数运算符"()"后,使用类变量调用函数运算符时,其行为类似函数调用,所以也称为仿函数(functor)。

lambda表达式是函数对象的语法糖,使用三种括号来定义:

[](){};
[]内可以是空白,表示不捕获任何lambda表达式外部的任何变量,其内也可以声明需要捕获的lambda表达式外部的变量,可以是值捕获,也可以是引用捕获。

()内用于定义lambda表达式的参数;

{}内用于定义语句体,相当于函数的函数体。

lambda表达式直接调用的语法形式:

[](){}(); // 第二对小括号()表达式表示调用,内部的值对应第一对小括号()内声明的参数。
操作参数化是指用函数指针、函数对象或lambda表达式做函数参数。

lambda表达式这种语法形式的引入主要用于操作参数化。

1 成员函数与函数对象
成员函数:

include

class AddNum{
public:

AddNum(int num):num_(num){}
int addNum(int x)const{
    return num_+x;
}

private:

int num_;

};

int main() {

auto add_num = AddNum(10);
auto x = add_num.addNum(5);
std::cout<<"x:"<<x<<std::endl;
return 0;

}
将成员函数改写为函数对象的形式:

include

class AddNum{
public:

AddNum(int num):num_(num){}
int operator()(int x)const{
    return num_+x;
}

private:

int num_;

};

int main() {

auto add_num = AddNum(10);
auto x = add_num(5);
std::cout<<"x:"<<x<<std::endl;
return 0;

}
2 从函数对象到lambda表达式
lambda表达式:

include

int main() {

auto x = num=10{return num + x;}(5);
std::cout<<"x:"<<x<<std::endl;
return 0;

}
lambda表达式是函数对象的语法糖。

也可以对lambda表达式进行命名,命名后可以如同函数一样调用:
//代码效果参考:http://www.zidongmutanji.com/bxxx/162556.html

include

int main() {

auto add_num = num=10 {return num + x;};
auto x = add_num(5);
std::cout<<"x:"<<x<<std::endl;
return 0;

}
auto推导的lambda表达式类型相当于以下类型:

include

include

int main() {

std::function<int(int)> add_num = num=10 {return num + x;};
auto x = add_num(5);
std::cout<<"x:"<<x<<std::endl;
return 0;

}
3 操作参数化
操作参数化也就是用函数指针、函数对象或lambda表达式做函数参数。

如for_each()函数:

template
Function for_each(InputIterator first, InputIterator last, Function fn)
{

while(first!=last) {
    fn (*first); // fn是for_each的参数,first也是,同时也是fn的参数
    ++first;
}
return fn;      // or, since C++11: return move(fn);

}
3.1 使用函数指针让操作参数化

include

include

include

void print_int(int x){

std::cout<<"x: "<<x<<std::endl;

}
int main() {

std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),print_int);
return 0;

}
3.2 使用函数对象让操作参数化

include

include

include

struct print_int{

void operator()(int x){
    std::cout<<"x: "<<x<<std::endl;
}

};
int main() {

std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),print_int());
return 0;

}
3.3 使用lambda表达式让操作参数化

include

include

include

int main() {

std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),[](int x){std::cout<<"x: "<<x<<std::endl;});
return 0;

}
4 lambda表达式还可以捕获表达式外部的变量
4.1 按值捕获

include

include

include

int main() {

int times = 2;
int others = 3;
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),times{std::cout<<"x: "<<x*times<<std::endl;}); // 按值捕获times
return 0;

}
也可以全部按值捕获:

include

include

include

//代码效果参考:http://www.zidongmutanji.com/bxxx/484144.html

int main() {

int times = 2;
int others = 3;
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),={std::cout<<"x: "<<x*times*others<<std::endl;}); // [=]表示全部按值捕获
return 0;

}
4.2 按引用捕获

include

include

include

int main() {

int times = 2;
int others = 3;
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),×{std::cout<<"x: "<<x*++times<<std::endl;}); // [×]表示按引用捕获times
return 0;

}
也可以全部按引用捕获:

include

include

include

//代码效果参考:http://www.zidongmutanji.com/bxxx/472460.html

int main() {

int times = 2;
int others = 3;
std::vector<int> arr = {1,3,5,7,9};
std::for_each(arr.begin(),arr.end(),&{std::cout<<"x: "<<x*++times*++others<<std::endl;}); // [&]表示全部引用
return 0;

}

相关文章
|
2月前
|
C++
C++ 语言异常处理实战:在编程潮流中坚守稳定,开启代码可靠之旅
【8月更文挑战第22天】C++的异常处理机制是确保程序稳定的关键特性。它允许程序在遇到错误时优雅地响应而非直接崩溃。通过`throw`抛出异常,并用`catch`捕获处理,可使程序控制流跳转至错误处理代码。例如,在进行除法运算或文件读取时,若发生除数为零或文件无法打开等错误,则可通过抛出异常并在调用处捕获来妥善处理这些情况。恰当使用异常处理能显著提升程序的健壮性和维护性。
51 2
|
2月前
|
算法 C语言 C++
C++语言学习指南:从新手到高手,一文带你领略系统编程的巅峰技艺!
【8月更文挑战第22天】C++由Bjarne Stroustrup于1985年创立,凭借卓越性能与灵活性,在系统编程、游戏开发等领域占据重要地位。它继承了C语言的高效性,并引入面向对象编程,使代码更模块化易管理。C++支持基本语法如变量声明与控制结构;通过`iostream`库实现输入输出;利用类与对象实现面向对象编程;提供模板增强代码复用性;具备异常处理机制确保程序健壮性;C++11引入现代化特性简化编程;标准模板库(STL)支持高效编程;多线程支持利用多核优势。虽然学习曲线陡峭,但掌握后可开启高性能编程大门。随着新标准如C++20的发展,C++持续演进,提供更多开发可能性。
49 0
|
4天前
|
算法 编译器 程序员
C++ 11新特性之Lambda表达式
C++ 11新特性之Lambda表达式
|
20天前
|
JavaScript 前端开发 测试技术
一个google Test文件C++语言案例
这篇文章我们来介绍一下真正的C++语言如何用GTest来实现单元测试。
14 0
|
2月前
|
编译器 C++ 容器
C++语言的基本语法
想掌握一门编程语言,第一步就是需要熟悉基本的环境,然后就是最重要的语法知识。 C++ 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 - 摇动、叫唤、吃。对象是类的实例。 类 - 类可以定义为描述对象行为/状态的模板/蓝图。 方法 - 从基本上说,一个方法表示一种行为。一个类可以包含多个方法。可以在方法中写入逻辑、操作数据以及执行所有的动作。 即时变量 - 每个对象都有其独特的即时变量。对象的状态是由这些即时变量的值创建的。 完整关键字
53 2
|
3月前
|
前端开发 编译器 程序员
协程问题之为什么 C++20 的协程代码比其他语言的协程 demo 长很多如何解决
协程问题之为什么 C++20 的协程代码比其他语言的协程 demo 长很多如何解决
|
3月前
|
安全 编译器 C++
C++一分钟之-泛型Lambda表达式
【7月更文挑战第16天】C++14引入泛型lambda,允许lambda接受任意类型参数,如`[](auto a, auto b) { return a + b; }`。但这也带来类型推导失败、隐式转换和模板参数推导等问题。要避免这些问题,可以明确类型约束、限制隐式转换或显式指定模板参数。示例中,`safeAdd` lambda使用`static_assert`确保只对算术类型执行,展示了一种安全使用泛型lambda的方法。
43 1
|
4月前
|
存储 Java C#
C++语言模板类对原生指针的封装与模拟
C++|智能指针的智能性和指针性:模板类对原生指针的封装与模拟
|
4月前
|
程序员 编译器 C++
探索C++语言宝库:解锁基础知识与实用技能(类型变量+条件循环+函数模块+OOP+异常处理)
探索C++语言宝库:解锁基础知识与实用技能(类型变量+条件循环+函数模块+OOP+异常处理)
37 0
|
4月前
|
存储 编译器 开发工具
C++语言教程分享
C++语言教程分享
下一篇
无影云桌面