c++ 不定参函数初探

这里由于代码需要其实是自己懒自行研究了一下 C++ 的不定参系统。这篇文章对于 OIer 来说应该是够用了。

代码均以求若干个数的模 mod 意义下和为例子。


va_list 系 (C)

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
#include<cstdarg>

int Add(int argc, ...) {
int ans = 0;
va_list argv;
va_start(argv, argc);
while (argc--)
ans = (ans + va_arg(args, int)) % mod;
va_end(argv);
return ans;
}

Add(6, 1, 1, 4, 5, 1, 4); // returns 16 % mod;

优点

C 语言只能用这个,就没啥别的优点了(

这个在 C 库的应用比较广泛,所以应该熟练掌握如何调用(大雾

缺点

拥有 C 的各种缺点。传参直接面向内存,导致类型转换非常麻烦,容易出错和越界。

必须传一个参数使得能够推断出参数类型和个数,非常麻烦。比如 printf 就要传一个 const char*,用格式符推断类型和个数。

格式十分严格,不加 va_end 会引发内存问题。


模板类 (C++)

示例

1
2
3
4
5
6
7
8
9
10
int Add(int t) {
return (t % mod + mod) % mod;
}

template<typename... Ts>
int Add(int t, Ts... r) {
return ((t + Add(r...)) % mod + mod) % mod;
}

Add(1, 1, 4, 5, 1, 4); // returns 16 % mod

优点

写起来帅。在 C++98 中可用,可读性也比较高。

调用起来比较省心,不会反直觉,是真正意义上的不定参(

缺点

只能递归调用,会带来一定的常数。

写的时候要注意是从右往左推上来的,要细心处理,不然容易错。


std::initializer_list (C++11)

示例

1
2
3
4
5
6
7
8
9
10
#include<initializer_list>

int Add(const std::initializer_list<int> &z) {
int ans = 0;
for (int x : z)
ans = (ans + x) % mod;
return (ans % mod + mod) % mod;
}

Add({1, 1, 4, 5, 1, 4}); // returns 16 % mod;

优点

写起来方便,完全符合 C++ 具名规范,容易操作。

这一个优点就够强了,还要啥自行车(

缺点

调用的时候那个花括号太难受了(

感觉上 STL 可能会带个大常数,实际上跟模板写法的递归差不多(O2)。

文章作者: fa_555
文章链接: https://blog.fa555.tech/2020/cpp%E4%B8%8D%E5%AE%9A%E5%8F%82%E5%87%BD%E6%95%B0%E5%88%9D%E6%8E%A2/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 fa_555's Blog