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

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


我在刷牛客网的题时,遇到了运行速度太大,查看了已提交的代码,发现都有一段代码,就是题目中的,查阅了大家的博客,学习了一下,提高运行速度的方法,就是在最前面加这段代码。

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;
}();

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

转载:https://blog.csdn.net/qq_32320399/article/details/81518476 

解析

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 :: cinstd :: cout为了兼容C,保证在代码中同时出现std :: cinscanfstd :: coutprintf时输出不发生混乱,所以C++用一个流缓冲区来同步C的标准流。通过std :: ios_base :: sync_with_stdio函数可以解除这种同步,让std :: cinstd :: 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 :: cinstd :: cout之间的绑定,来降低IO的负担使效率提升。

注意

使用std::ios::sync_with_stdio(false)std::cin.tie(nullptr)之后要避免和scanfprintf混用以避免出现问题。

疑惑

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

本以为效率提升的主要原因就是std::ios::sync_with_stdio(false)std::cin.tie(nullptr),可是我将这两个函数调用写在一个函数中并调用或者是直接在函数体中调用,提交之后都会通不过,并同样提示以下错误

Runtime Error Message:  terminate called after throwing an instance of ‘std::logic_error’
                         what(): basic_string::_M_construct null not valid
Last executed input:      “IV”

随手查了以下,有说是“将空指针赋给std :: string”的也有说是“输入测试案例时格式不符合要求,比如有多余的空格等”,具体是什么原因暂时先不看了,在此占个坑,等有空再填。


参考资料

C++11语言扩展:常规特性
C++ 11 Lambda表达式(@滴水瓦)
C++ reference
http://www.cplusplus.com/
关于ios::sync_with_stdio(false);和 cin.tie(0)加速c++输入输出流

猜你喜欢

转载自blog.csdn.net/qq_41103495/article/details/108505064
今日推荐