解析 static auto x = []() { std::ios::sync_with_stdio(false);std::cin.tie(nullptr);return 0;}()
前言
这两天在LeetCode上刷题的时候看见有好几个速度排名第一的代码中都有一段类似的代码,如下:
static const auto io_sync_off = []()
{// turn off syncstd::ios::sync_with_stdio(false);// untie in/out streamsstd::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……..
随手记
此问题发现自LeetCode题目13. Roman to Integer,尚未对其他题目进行测试
本以为效率提升的主要原因就是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++输入输出流
解析 static auto x = []() { std::ios::sync_with_stdio(false);std::cin.tie(nullptr);return 0;}()相关推荐
- 【C++】ios::sync_with_stdio(false) 与 cin.tie(nullptr) 加速 IO
目录&索引 一.前言 题目 二.ios::sync_with_stdio(false) 三.cin.tie(nullptr) 四.小结 一.前言 之前写题遇到大数据量(cin.cout 数据量 ...
- 关于ios::sync_with_stdio(false);和 cin.tie(0)加速c++输入输出流
原文地址:http://www.hankcs.com/program/cpp/cin-tie-with-sync_with_stdio-acceleration-input-and-output.ht ...
- leetcode练习——数组篇(1)(std::ios::sync_with_stdio(false);std::cin.tie(nullptr);)
题号1. 两数之和: 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复 ...
- C++输入输出流加速器,关闭同步流,ios::sync_with_stdio(false)和 cin.tie(0)
leetcode练习时,总会发现运行时间短的代码都会有类似: static int x=[](){std::ios::sync_with_stdio(false);cin.tie(NULL);retu ...
- std::ios::sync_with_stdio(false)的运用
c++中cin,cout效率比较低,是因为先把要输出的东西存入缓冲区与C语言中的stdio同步后,再输出,导致效率降低,而这段语句的作用是取消缓冲区同步,直接使用,由此可节省时间,使效率与scanf与 ...
- 关于std::ios::sync_with_stdio(false)
std::ios::sync_with_stdio(false); 很多C++的初学者可能会被这个问题困扰,经常出现程序无故超时,最终发现问题处在cin和cout上,(甚至有些老oier也会被这个问题 ...
- C++ 里利用 std::ios::sync_with_stdio(false) 解决TLE问题
2018-1-23 关于用C++里面的cin读取数据,我们都知道它的速度相对于C里面的scanf是比较慢的... 首先,我随机生成了10000000个整数 #include<stdio.h> ...
- std::ios::sync_with_stdio(false);
这句语句是用来取消cin的同步,什么叫同步呢?就是iostream的缓冲跟stdio的同步.如果你已经在头文件上用了using namespace std;那么就可以去掉前面的std::了.取消后就c ...
- 拾趣——ios::sync_with_stdio(false)详解(提高代码运算速度)
本篇文章核心意思:在编程时cin(cout)比scanf(printf)慢,在代码里加上ios::sync_with_stdio(false) 这个语句后,cin(cout)速度就会变得和scanf( ...
最新文章
- SKU表管理之删除SKU表数据
- P4735 最大异或和(可持久化trie树、求最大区间异或和)
- eclipse 自动生成代码
- java socket 字节读取_Java SocketChannel 读取ByteBuffer字节的处理模型
- 【实战】某学校机房项目交换机的配置
- 【收藏】nvm的下载,安装与使用(nodejs版本管理)
- sql更新表的字段和主键
- 回归统计在DMP中的实战应用
- php连接mysql的方式_php有几种连接mysql的方法
- c语言 调用父类方法,关于C++:如何从派生类函数调用父类函数?
- Modelsim缺失库快速添加
- JAVA判断素数法+引用方法
- ISO 9001是什么?ISO 9001 质量管理体系详细介绍
- java实训心得体会3篇_java实训心得体会3篇
- .ipynb_checkpoints隐藏文件引发的错误
- 闹归闹,还是要说几件正事
- 新网银行金融科技挑战赛 AI算法赛道 亚军方案
- iOS开发之沙盒机制(SandBox)
- 2021研面准备 -- 计算机网络知识点整理(一)概述
- Android自定义TabBar