前言
这两天在LeetCode上刷题的时候看见有好几个速度排名第一的代码中都有一段类似的代码,如下:
static const auto io_sync_off = []() { // turn off sync std::ios::sync_with_stdio(false); // untie in/out streams std::cin.tie(nullptr); return nullptr; }();
看到这个内心是比较懵逼的,首先这个语法就没见过,而且当我把这段代码复制到我的代码中之后,我的代码运行速度一下从48ms提升到24ms,不得不说还是很震惊的,毕竟在什么都没改动的情况下仅仅是添加了这段代码后速度竟然提升了这么多。因此去查了查这段代码是什么意思,在此做个记录。
解析
1. Lambda
首先先说一下这个语法
static const auto io_sync_off = [](){ ... ... }();
c++11的新特性,没有好好研究过啊,还需要多学习。(c++ Primer 第十章泛型算法中有提到)
Lambda也可以看做一种函数的定义方式,不过可以在函数内部声明定义 并且直接使用,必须使用尾置返回,并且是一个可调用对象,可以使用调用运算符(())(没错就是这个括号,跟在函数后面的)。
这里的[]即捕获列表,可以捕获所在函数中的局部变量,()代表了参数括号,参数为空,也可以省去括号(Lambda中不支持默认参数),函数体和捕获列表不能省去。
Lambda表达式是C++11引入的特性,是一种描述函数对象的机制,它的主要应用是描述某些具有简单行为的函数。Lambda也可以称为匿名函数。
原来还真是函数的一种写法(因为与开始我所描述的问题并不是直接原因,在此并不展开细讲,感兴趣的话可参考滴水瓦的文章C++ 11 Lambda表达式),所以上面的语法应该等价于
static const auto function() { ... ... } static const auto io_sync_off = function();
2.std::ios::sync_with_stdio(false);
函数std :: ios_base :: sync_with_stdio的解释是
Sets whether the standard C++ streams are synchronized to the standard C streams after each input/output operation.
设置在每次输入/输出操作后标准C ++流是否与标准C流同步
随后又看到了一段关于std :: cin的解释
The global objects std::cin and std::wcin control input from a stream buffer of implementation-defined type (derived from std::streambuf), associated with the standard C input stream stdin. These objects are guaranteed to be constructed before the first constructor of a static object is called and they are guaranteed to outlive the last destructor of a static object, so that it is always possible to read from std::cin in user code. Unless sync_with_stdio(false) has been issued, it is safe to concurrently access these objects from multiple threads for both formatted and unformatted input. Once std::cin is constructed, std::cin.tie() returns &std::cout, and likewise, std::wcin.tie() returns &std::wcout. This means that any formatted input operation on std::cin forces a call to std::cout.flush() if any characters are pending for output.
这个现在看起来就比较容易理解了,因为std :: cin默认是与std :: cout绑定的,所以每次操作的时候(也就是调用”<<”或者”>>”)都要刷新(调用flush),这样增加了IO的负担,通过tie(nullptr)来解除std :: cin和std :: cout之间的绑定,来降低IO的负担使效率提升。
注意
使用std::ios::sync_with_stdio(false)和std::cin.tie(nullptr)之后要避免和scanf和printf混用以避免出现问题。
总结
这段函数的主要作用就是提高输入输出的速度,貌似是好多竞赛大佬都用的,我只能瑟瑟发抖了。
参考资料
C++11语言扩展:常规特性
C++ 11 Lambda表达式(@滴水瓦)
C++ reference
http://www.cplusplus.com/
关于ios::sync_with_stdio(false);和 cin.tie(0)加速c++输入输出流
解析 static auto x = []() { std::ios::sync_with_stdio(false);std::cin.tie(nullptr);return 0;}()