0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C++禁用同步的方式

C语言与CPP编程 来源:C语言与CPP编程 作者:C语言与CPP编程 2022-10-17 09:05 次阅读

恰好之前研究过这块,所以借助本文,分析下这个问题(无意于语言之争,单纯是从技术角度)。

众所周知,C++兼容了C的所有功能,显然从所有角度去对比分析是不现实的,所以本文从我们常用的输入输出即标准流(iostream和stdio)的角度来分析讲解。

示例

为了更加直观地来对比分析,写了个示例,通过scanf和cin读文件,然后分析两种方式的性能高低,代码如下:

#include
#include
#include
#include
constintnum=1000000;

voidtime_report(conststd::function&f1,conststd::function&f2){
autostart=std::now();
f1();
autoend=std::now();
std::cout<< "cin cost " << std::duration_cast(end-start).count()<< "ms" << std::endl;

   start = std::now();
   f2();
   end = std::now();
   std::cout << "scanf cost " << std::duration_cast(end-start).count()<< "ms" << std::endl;
}


void write() {
  std::ofstream file("./data");
  for(int i = 0; i < num; ++i) {
    file << rand() <<' ';
    if((i + 1) % 20 == 0) {
      file << std::endl;
    }
  }
}
int main() {
  write(); 
  
  time_report([](){
  freopen("./data","r",stdin);
  int n = 0;
  for(int i=0; i>n;
}
},[](){
freopen("./data","r",stdin);
intn=0;
for(inti=0;i< num; ++i) {
     scanf("%d", &n);
  }
});

return 0;
}

编译,运行之后,输出如下:

cincost686ms
scanfcost189ms

从上述输出来看,cin的耗时是scanf的3倍多,果真如此么?

sync_with_stdio

C++性能真的差C这么多吗?直接颠覆了对C++的认知,即使性能真的低,也得知道为什么低吧,于是开始研究,发现C++为了兼容C,在C标准流(stdio)和C++标准流(iostrem)保持同步,这样就可以混合使用C和C++风格的I/O,且能保证得到合理和预期的结果,而正是这个同步导致C++在cin性能上有损失。如果禁用同步,则允许C++流拥有自己的独立缓冲区,这样性能就会提升很多。

那么是否可以禁用该同步功能呢?

C++提供了一个函数std::sync_with_stdio,声明如下:

staticboolsync_with_stdio(bool__sync=true);

如果参数为false,则代表禁用此同步。从上面声明可以看出,默认情况下__sync = true也就是说禁用同步,而如果__sync为false的话,则会有如下操作:

bool
ios_base::sync_with_stdio(bool__sync){
bool__ret=ios_base::_S_synced_with_stdio;

if(!__sync&&__ret){
//...
cout.rdbuf(&buf_cout);
cin.rdbuf(&buf_cin);
cerr.rdbuf(&buf_cerr);
clog.rdbuf(&buf_cerr);
//...
}
return__ret;
}

从上述代码,进一步验证了我们上面的说法,如果禁用了同步功能,则C++流使用自己的缓冲区buf_cin(此处以cin为例),几种buffer的定义如下:

typedefcharfake_filebuf[sizeof(stdio_filebuf)]
__attribute__((aligned(__alignof__(stdio_filebuf))));
fake_filebufbuf_cout;
fake_filebufbuf_cin;
fake_filebufbuf_cerr;

好了,截止到现在,我们已经搞清楚了为什么C++流性能要慢于C,为了验证是否真的是因为使用了同步功能而导致的性能差异,使用std::sync_with_stdio(false)关闭同步,代码示例如下:


#include

#include #include #include constintnum=1000000; voidtime_report(conststd::function&f1,conststd::function&f2){ autostart=std::now(); f1(); autoend=std::now(); std::cout<< "cin cost " << std::duration_cast(end-start).count()<< "ms" << std::endl;    start = std::now();    f2();    end = std::now();    std::cout << "scanf cost " << std::duration_cast(end-start).count()<< "ms" << std::endl; } void write() {   std::ofstream file("./data");   for(int i = 0; i < num; ++i) {     file << rand() <<' ';     if((i + 1) % 20 == 0) {       file << std::endl;     }   } } int main() {   std::sync_with_stdio(false);   write();       time_report([](){   freopen("./data","r",stdin);   int n = 0;   for(int i=0; i>n; } },[](){ freopen("./data","r",stdin); intn=0; for(inti=0;i< num; ++i) {      scanf("%d", &n);   } }); return 0; }

编译,运行后,输出如下:

cincost178ms
scanfcost189ms

可以看出禁用同步后,二者的性能基本一致。

既然禁用同步后,C++流的性能与C基本一致,那么是否直接禁用呢?答案是依赖于具体的使用场景。

1、同步的C++流是线程安全的,也就说来自不同线程的输出可能会交错,但数据不会产生竞争,而如果禁用同步,则可能出现意想不到的结果。

2、如果禁用了同步功能,输入输出顺序可能会得不到我们想要的结果。

#include
#include

intmain(){
std::cout<< "a ";
  printf("b ");
  std::cout << "c ";
  return 0;
}

上述代码执行后,输出a b c ,符合我们的预期。

如果加上禁用同步代码,如下:

#include
#include

intmain(){
std::sync_with_stdio(false);
std::cout<< "a ";
printf("b ");
std::cout << "c ";

return 0;
}

编译、运行之后,结果为a c b,与我们期望的不一致。

结语

如果使用C编程,那么使用C stdio,而如果使用C++编程,则建议使用C++ I/O。如果在某些特殊场景下,需要混合使用,那么强烈建议不要禁用同步,否则会得到意想不到的结果。

好了,今天的文章就到这,我们下期见!

审核编辑:彭静
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 编程
    +关注

    关注

    88

    文章

    3587

    浏览量

    93578
  • C++
    C++
    +关注

    关注

    22

    文章

    2104

    浏览量

    73480
  • 代码
    +关注

    关注

    30

    文章

    4741

    浏览量

    68324

原文标题:C++性能真的不如C吗?

文章出处:【微信号:C语言与CPP编程,微信公众号:C语言与CPP编程】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言与C++的区别

    在很大程度上,C++C的超集,这意味着一个有效的C程序也是一个有效的C++程序。
    发表于 09-16 10:20 1128次阅读

    C语言实现面向对象的方式 C++中的class的运行原理

    这里主要介绍下在C语言中是如何实现的面向对象。知道了C语言实现面向对象的方式,再联想下,C++中的class的运行原理是什么?
    发表于 10-21 09:00 1111次阅读

    C++C/C++程序设计教程_C/C++概述

    C++基础知识,简要介绍了C++的一些简单知识,概念,函数
    发表于 12-25 10:15 0次下载

    如何提高cc++的安全编程能力?《CC++安全编码》带你详细学习

    ,既详细阐述了C/C++语言及其相关库固有的安全问题和陷阱,系统总结了导致软件漏洞的各种常见编码错误,并给出了应对错误的解决方案;又对C/C++软件中常见漏洞的危害、被利用
    发表于 08-28 08:00 0次下载

    VISUAL C++教程之VISUAL C++的安装和使用方法

    本文档的主要内容详细介绍的是VISUAL C++教程之VISUAL C++的安装和使用方法资料免费下载。
    发表于 12-27 16:32 19次下载
    VISUAL <b class='flag-5'>C++</b>教程之VISUAL <b class='flag-5'>C++</b>的安装和使用方法

    C++程序设计教程之C++的初步知识的详细资料说明

    C++程序设计教程之C++的初步知识的详细资料说明包括了:1. 从CC++,2 . 最简单的C++程序,3 .
    发表于 03-14 14:48 31次下载
    <b class='flag-5'>C++</b>程序设计教程之<b class='flag-5'>C++</b>的初步知识的详细资料说明

    C语言与C++相互调用

        1CC++相互调用 在一个嵌入式系统中大部分的底层和驱动层更多的是采用C语言来进行开发,而上层应用、服务更多的采用C++等高级语言来进行面向对象等方面的开发
    的头像 发表于 01-18 11:05 3277次阅读
    <b class='flag-5'>C</b>语言与<b class='flag-5'>C++</b>相互调用

    C++学习笔记之c++的基本认识

    自这篇文章我们即将开始C++的奇幻之旅,其内容主要是读C++ Primer的总结和笔记,有兴趣可以找原版书看看,对于学习C++还是有很大帮助的。这篇文章将从一个经典的程序开始介绍C++
    的头像 发表于 03-17 13:57 700次阅读

    C/C++编译器的缺省字节对齐方式

    C/C++编译器的缺省字节对齐方式为自然对界。即在缺省情况下,编译器为每一个变量或是数据单元按其自然对界条件分配空间。
    的头像 发表于 04-15 11:24 954次阅读

    浅谈C语言与C++的前世今生

    C++开发人员将有这些问题归咎于C,而C开发人员则认为C++过于疯狂。我觉得站在C的角度看C++
    发表于 05-26 09:27 431次阅读
    浅谈<b class='flag-5'>C</b>语言与<b class='flag-5'>C++</b>的前世今生

    c++入门后如何进阶

    C++11 是下一个 C++ 标准,但我们通常称之为现代 C++。现代 C++ 也包括了 C++14 和
    发表于 07-21 08:56 322次阅读
    <b class='flag-5'>c++</b>入门后如何进阶

    C++之父新作带你勾勒现代C++地图

    为了帮助大家解决这些痛点问题,让大家领略现代C++之美,掌握其中的精髓,更好地使用C++C++之父Bjarne Stroustrup坐不住了,他亲自操刀写就了这本《C++之旅》!
    的头像 发表于 10-30 16:35 792次阅读
    <b class='flag-5'>C++</b>之父新作带你勾勒现代<b class='flag-5'>C++</b>地图

    c++多行注释快捷键

    C++中,多行注释(也称为块注释)是一种用于注释大段代码或多个语句的方法。当你希望暂时禁用一些代码或者解释特定部分代码的作用时,多行注释是非常有用的。 在C++中,多行注释以 /* 开始,以
    的头像 发表于 11-22 10:24 8148次阅读

    C++简史:C++是如何开始的

    MISRA C++:2023,MISRA® C++ 标准的下一个版本,来了!为了帮助您做好准备,我们介绍了 Perforce 首席技术支持工程师 Frank van den Beuken 博士撰写
    的头像 发表于 01-11 09:00 528次阅读
    <b class='flag-5'>C++</b>简史:<b class='flag-5'>C++</b>是如何开始的

    C/C++中两种宏实现方式

    #ifndef的方式C/C++语言标准支持。它不仅可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件(或者代码片段)不会被不小心同时包含。
    的头像 发表于 04-19 11:50 547次阅读