目录
- 1、背景知识
- 2、`ios::sync_with_stdio(false)`
-
- [2.1 **作用**](#2.1 作用)
- [2.2 原理](#2.2 原理)
- [2.3 注意事项](#2.3 注意事项)
- 3、`cin.tie(0)`
-
- [3.1 作用](#3.1 作用)
- [3.2 原理](#3.2 原理)
- [3.3 注意事项](#3.3 注意事项)
- 4、代码演示
- 5、实例操作
-
- [5.1 创建数据文件](#5.1 创建数据文件)
- [5.2 进行代码演示](#5.2 进行代码演示)

1、背景知识
- 在 C++ 中,标准输⼊输出流如 cin 和 cout 是由 C++ 的标准库提供的;而在 C 语言中,标准输入输出函数如 scanf 和 printf 是由 C 标准库提供的。由于 C++ 是从 C发展而来的语言,C++ 标准库的输入输出流系统需要与 C 标准库的输入输出系统兼容,以确保在同一程序中能够混合使用 C 和 C++ 的输⼊输出函数。为了实现这种兼容性,C++标准库默认会将 cin 、 cout 等 C++ 流对象与 stdin 、 stdout 等 C 标准库的流对象同步在⼀起(流同步) 。这种同步操作意味着每次使用 cin 或 cout 时,都会自动刷新 C 标准库的缓冲区,以确保 C++ 和 C 的 I/O 是⼀致的,这就导致了效率问题。
- 在默认情况下, cin 和 cout 之间存在⼀种绑定关系 。这种绑定意味着,每当从cin 读取数据时,任何之前通过 cout 输出的内容都会被强制刷新到屏幕上。这个机制保证了输出内容能够立即显示给用户,这对于交互式程序非常有用。但是,这种绑定也可能导致性能问题,特别是在需要频繁读取大量数据的情况下。这是因为每次从 cin 读取数据都会触发⼀次输出缓冲区的刷新,即使实际上没有进行输出操作,也会浪费时间。
你也可以从C++
的相关网站上看到这两点:
2、ios::sync_with_stdio(false)
2.1 作用
调用ios::sync_with_stdio(false)
可以关闭C++
标准库与C
标准库之间的I/O同步
,这意味着C++
标准库的cin
和cout
将不再与C
的stdin
和stdout
同步,以及cin
和cout
的I/O
操作将不再自动刷新C
标准库的缓冲区,这减少了不必要的同步开销,从而提高了I/O
操作的效率。
2.2 原理
默认情况下,ios::sync_with_stdio(true)
会使 cin 、cout
等流对象与stdin 、stdout
等流对象同步。这种同步操作会在每次I/O
操作时确保两者之间的数据⼀致性,但也会增加额外的性能开销。
当你调用ios::sync_with_stdio(false)
时,C++
标准库会解除这种同步,从而允许cin和cout
的 I/O
操作以更高的效率独立进行。
2.3 注意事项
混用C和C++ I/O
函数 :如果你的程序既使用了C的I/O函数
,如printf、scanf
,又使用了C++的 I/O 函数
,如cin、cout
,则不建议使用sync_with_stdio(false)
,因为这可能导致不可预期的行为 ,如输出顺序错乱。
线程安全性 :解除同步后,I/O
操作可能不再是线程安全的,特别是在多线程环境中需要谨慎使用。
3、cin.tie(0)
3.1 作用
取消cin与cout
之间的绑定。这样⼀来,当从cin
读取数据时,cout
的缓冲区就不会被刷新。这可以提高输入操作的速度,尤其是在需要处理大量数据的情况下。
3.2 原理
在默认情况下,cin和cout
之间存在⼀种绑定关系 。这种绑定意味着,每当从cin
读取数据时,任何之前通过cout
输出的内容都会被强制刷新到屏幕上。这个机制保证了输出内容能够立即显示给用户,这对于交互式程序非常有用。但是,这种绑定也可能导致性能问题,特别是在需要频繁读取大量数据的情况下。这是因为每次从cin
读取数据都会触发⼀次输出缓冲区的刷新,即使实际上没有进行输出操作,也会浪费时间。
3.3 注意事项
程序逻辑 :在某些依赖于默认绑定行为的程序中,取消绑定可能会导致程序逻辑错误。例如,如果期望在读取输入前能看到提示信息,则需要显式地调用cout的flush
方法确保输出被刷新。
4、代码演示
cpp
#include <iostream>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int a;
cin >> a;
cout << a << endl;
return 0;
}
当你的做题经验丰富时,你可以总结出以下几点:
- 当输入的数据量比较小
(10^6以内)
时,使用cin和cout
或scanf和printf
都可以; - 当输入的数据量比较大
(10^9左右)
时,更推荐使用scanf和printf
或优化后的cin和cout
。
5、实例操作
我们创建一个有一千万个数据的文件,然后分别使用cin和cout
、scanf和printf
、优化后的cin和cout
进行读写操作,分别查看程序的运行所需时间。
5.1 创建数据文件
利用我们之前博客中讲过的文件操作创建数据文件。
cpp
void creatdata()
{
int num = 10000000;
FILE* file = fopen("data.txt", "w");
if (file == nullptr)
{
perror("fopen fail!");
exit(1);
}
for (int i = 0;i < num;i++)
{
fprintf(file, "%d ", i);
}
fclose(file);
}
准备进度 :
这里我们已经将我们的数据文件创建出来了一共有一千万个数字(从0到9999999)
。
5.2 进行代码演示
cin和cout
:
cpp
#include <iostream>
#include <ctime>
#include <vector>
#include <cstdio>
using namespace std;
const int num = 10000000;
int main()
{
freopen("data.txt", "r", stdin);
vector<int> v;
clock_t t1, t2;
t1 = clock();//获取开始时间
for (int i = 0;i < num;i++)
{
int x;
cin >> x;
v.push_back(x);
}
//这里输出一部分数据,否则太耗时
for (int i = 0;i < 100000;i++)
{
cout << v[i] << " ";
}
t2 = clock();//获取结束时间
system("cls");//清屏,便于获取数据
cout << "runtime of cin、cout:" << t2 - t1 << "ms" << endl;
return 0;
}
运行结果 :
这里运行花费了28秒 。
scanf和printf
:
cpp
#include <iostream>
#include <ctime>
#include <vector>
#include <cstdio>
using namespace std;
const int num = 10000000;
int main()
{
freopen("data.txt", "r", stdin);
vector<int> v;
clock_t t1, t2;
t1 = clock();//获取开始时间
for (int i = 0;i < num;i++)
{
int x;
scanf("%d", &x);
v.push_back(x);
}
//这里输出一部分数据,否则太耗时
for (int i = 0;i < 100000;i++)
{
printf("%d ", v[i]);
}
t2 = clock();//获取结束时间
system("cls");//清屏,便于获取数据
cout << "runtime of scanf、printf:" << t2 - t1 << "ms" << endl;
return 0;
}
运行结果 :
这里运行花费了4秒 ,和上面的cin和cout
进行对比发现,当数据量足够大时,耗费的时间成倍增长,使用cin和cout
很有可能在数据量很大的竞赛题目场景下,让你无法AC
题目。
我们再来看看优化后的cin和cout
:
cpp
#include <iostream>
#include <ctime>
#include <vector>
#include <cstdio>
using namespace std;
const int num = 10000000;
int main()
{
//取消给C语言输入输出缓冲区的同步
ios::sync_with_stdio(false);
//解除cin和cout的绑定
cin.tie(0);
freopen("data.txt", "r", stdin);
vector<int> v;
clock_t t1, t2;
t1 = clock();//获取开始时间
for (int i = 0;i < num;i++)
{
int x;
scanf("%d", &x);
v.push_back(x);
}
//这里输出一部分数据,否则太耗时
for (int i = 0;i < 100000;i++)
{
printf("%d ", v[i]);
}
t2 = clock();//获取结束时间
system("cls");//清屏,便于获取数据
cout << "runtime of cin、cout:" << t2 - t1 << "ms" << endl;
return 0;
}
运行结果 :
这次的运行时间缩减到了4秒,与scanf和printf
不相上下。这就是cin和cout
的优化。
总结:
以上就是本期博客分享的全部内容啦!如果觉得文章还不错的话可以三连支持一下,你的支持就是我前进最大的动力!
技术的探索永无止境! 道阻且长,行则将至!后续我会给大家带来更多优质博客内容,欢迎关注我的CSDN账号,我们一同成长!
(~ ̄▽ ̄)~