解析 static auto x = []() { std::ios::sync_with_stdio(false);std::cin.tie(nullptr);return 0;}()

前言
这两天在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 = [](){
    ... ...
}();


这个乍一看很像是函数,但是前后又是[]又是()的,还没函数名没返回值的,感觉又不太像,所以就去请教了一下别人,得到答案是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.

现在大概明白了一些,因为C++中的std :: cin和std :: cout为了兼容C,保证在代码中同时出现std :: cin和scanf或std :: cout和printf时输出不发生混乱,所以C++用一个流缓冲区来同步C的标准流。通过std :: ios_base :: sync_with_stdio函数可以解除这种同步,让std :: cin和std :: cout不再经过缓冲区,自然就节省了许多时间。

3. std::cin.tie(nullptr);
函数std :: ios :: tie的解释是

Get/set tied stream 
The first form (1) returns a pointer to the tied output stream.

The second form (2) ties the object to tiestr and returns a pointer to the stream tied before the call, if any.

The tied stream is an output stream object which is flushed before each i/o operation in this stream object.

C++11 
By default, the standard narrow streams cin and cerr are tied to cout, and their wide character counterparts (wcin and wcerr) to wcout. Library implementations may also tie clog and wclog.

这个现在看起来就比较容易理解了,因为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混用以避免出现问题。

疑惑
经过一番学习知道了一些加速方法,但我还是有一些疑惑。因为我的代码中并没有使用std :: cin和std :: cout,可是使用了std::ios::sync_with_stdio(false)和std::cin.tie(nullptr)之后代码的效率确实得到了大大的提升,现在能想到的解释只能是在评审的时候节省了用例的输入时间吧。emmmm……..
--------------------- 
原文:https://blog.csdn.net/qq_32320399/article/details/81518476 

你可能感兴趣的:(基础)