Lambda表达式
首先,Lambda读作 [‘læmdə]。
好,接下来我们步入正题。就我个人认为,Lambda表达式是一种能让一些不会经常调用的 简单函数 写得更简单的方法,其中最典型的例子就是sort
自定义排序函数。
假设我们有一个结构体node
如下:
1 | struct node{ |
一般来说,我们会写一个cmp
函数如下:
1 | bool cmp(node &a, node &b) { |
或者更高级一点,使用operator
重载运算符:
1 | struct node{ |
但是,这些写法都是需要额外再开一个函数的,并且对于先按某规则排序再按另一种规则排序这种情况的处理并不好(第二种写法甚至不能在这种情况下使用)。于是我们需要一种更简单的方法来写排序函数——Lambda表达式。先看效果,它写出来大概长这样:
1 | sort(points+1, points+n+1, [](node a, node b) -> bool { return (a.x==b.x?a.y<b.y:a.x<b.x); }); |
* 还能再简单点吗?
* 可以,那么就是这样:(下面代码中的-> bool
被省略了)
1 | sort(points+1, points+n+1, [](node a, node b) { return (a.x==b.x?a.y<b.y:a.x<b.x); }); |
这只是其中一种使用方法。借此,我们还可以把局部变量当做“全局”变量来用(并不是真的全局,但是在Lambda表达式的函数内可以使用这些局部变量),具体实现方法是 捕获 (这东西我还没想到在OI中的应用),也就是在那个[]
内部做文章,实现可以参考参考资料。
upd 20231130
除此之外,Lambda表达式还可以在函数内部定义函数,例如,我们可以在 main
函数里定义一个 add
函数用来给链式前向星加边:
1 | struct node{ |
而这个函数也是受“变量”的定义域所影响的,例如下面在 test
函数中调用 add()
函数将出现 $\text{CE}$ :
1 | struct node{ |
不仅如此,我们甚至可以在这基础上写递归(以 Tarjan
为例):
1 | struct node{ |
其主要就是一个 function
的实现,语法是 function<返回值类型(参数类型1, 参数类型2, ...)> = [捕获](传参){函数主体}
,而要递归就只用在捕获处引用这个函数(就像上面的例子)。
auto (C++11新语法)
先说怎么启用C++11或其他新版本,对于Dev-C++,在编译选项中的“在编译时添加这些参数”添加-std=c++11
,这里的 11
可以换为其他版本如:-std=c++23
。auto
可以自动匹配变量类型,但是没多大用(除非使用迭代器iterator
这种难写的类型),具体而言可以这么写:
1 | auto i = 1ll; |
(值得一提的是,使用迭代器遍历map
遍历出来的是pair
类型的东西)
并且,auto
还有一些可以减少代码量的用法,例如遍历vector
:
1 | for (int i = 0; i < (int)vec.size(); i++) { |
同理,其他能使用迭代器的容器都可以如此遍历(但是,栈和队列都不行)。
using
这个语法很简单,应用只有一个——using ll = long long
。
它能定义 ll
为 long long
并且还不能批量替换 int
。
如果要把代码中所有 int
替换为 long long
,请使用 #define int long long
(虽然这是未定义行为).
模块化思想 与 类和对象
将代码中实现不同功能的代码封装成函数,这会对 debug
有极大的帮助。
对象嘛,不是你想的那个对象,你可以使用 namespace
或 class
。
给个例子:
1 |
|
调试常用
离线比赛常用:cerr
因为离线比赛中需要进行文件输入输出,但是每次开关文件很麻烦,而 cerr
可以不受文件输入输出流影响,往标准输入输出流里进行输出,但代价是每次输出都会清理一遍缓冲区,时间消耗极大,所以调试完后一定一定要把所有 cerr
语句删除。
啥都能用的 assert
位于头文件 cassert
中,如果不用万能头要把头文件导入。
在代码中可以写 assert(a <= n && 1 <= a);
来判断 a
是否在给定的范围内,如果不在程序将立即终止运行并输出错误所在的行号等信息,准确来说,只要 assert
语句中的表达式的值为 false
,就会返回报错。
可以使用宏 #define NDEBUG
即可一次性禁用所有 assert
语句。
值得注意的是,在洛谷中,如果 assert
返回报错会显示 RE ,并返回错误信息:
1 | Runtime Error. |