如何优(装)雅(B)地使用C++

介绍一些冷门的C++语法特性,供压行选手使用(雾)

前置知识

  1. C++基础语法(
  2. 运算符重载
  3. template的初级应用(什么是初级呢,会用templatemax就好)
  4. functor(只会提及,了解即可)

正文

1.匿名函数(lambda表达式)

需要C++11
比赛可用:★★★☆☆
代码简化:★★★★☆
匿名函数应用于需要使用短函数的场合,或者函数需要修改此作用域内(非全局作用域)的局部变量的场合。
常见用法是使用sort的时候,需要传入一个cmp数组,但是自行定义又太过于繁琐,这时候可以直接使用lambda表达式。
基础格式:
[捕捉局部变量列表](参数){函数体}
例如,如果需要给point排序,以x为第一关键字从大到小排序,可以这么写:
sort(pi+1,pi+1+n,[](point a,point b){
   if(a.x != b.x)
       return a.x<b.x;
   return a.y<b.y;
});
lambda本质是一种functor,即重载了operator ()的类。
笔者曾经想使用lambda表达式作为返回值,然后就不想了
笔者曾经想使用lambda表达式来玩一些骚操作,然后被类型系统劝退了

2.语句内嵌表达式

无特殊要求
比赛可用:★★★★★
代码简化:★★☆☆☆
语句内嵌表达式应用于需要在传入一个值的场合运行一个表达式的情况。这么说可能有点抽象,具体来说,比如我们要执行以下程序段:
int a = query(1,1,n,l1,r1);
int b = query(1,1,n,l2,r2);
printf("%d",a+b+a*b);
这时候,就可以使用这样的语法来代替:
printf("%d",({
    const int a = query(1,1,n,l1,r1);
    const int b = query(1,1,n,l2,r2);
    a+b+a*b;
}));
也就是说,语句内嵌表达式的格式是这样子:
({
   语句1;
   语句2;
   ...
   语句n;
})
整个语句内嵌表达式的值就是最后一个语句(或者表达式)的值。其中语句可以是选择语句或循环语句,但是必须以一个单独的语句(或表达式)结尾作为值。
使用这种语法,
可以省掉一个if的大括号 可以强调ab的临时变量的地位(即ab只是为了计算而临时定义的),理论上来说会使程序更加清晰,实际上未必(糊)。不建议在其中使用过于复杂的逻辑。(会让代码看起来很乱,结构很不清晰紧凑)
这个语法看起来是C++11新增的好东西,其实在C99就有了(甚至可能更早),所以不用担心比赛的时候不能用。

3.复合字面量

无特殊要求
比赛可用:★★★★★
代码简化:★★★★☆
不想写构造函数?没关系!对于结构体,你可以使用复合字面量!
一看就懂!包学包会!省个函数!压行必备!
struct point
{
    int x;
    int y;
};

int main()
{
    point a = (point){1,2};
    printf("%d %d\n",a.x,a.y);
}
输出:1 2
我一开始还以为是stl::initializer_list<>初始化结构体的应用,直到我看到了C的标准

附录:效率问题

我就知道你们会关心效率问题
运行结果(皆重复100次):
操作传统文中
1:排序 10^6 个数10.16s7.432s
2:编译后查阅汇编码N/AN/A
3:不想测了,反正差不多N/AN/A
注:2中结果为汇编码相同
(操作1 文中方法比较快的原因似乎是lambda表达式会直接内联汇编进去,而函数指针不会)

参考资料

评论

此博客中的热门博文

将博客部署到星际文件系统(IPFS)

高中地理必修一知识点总结

一场CF的台前幕后(下)