More Effective C++ 条款23

条款23:考虑变更程序库

程序库的设计就是一个折衷的过程。理想的程序库应该是短小的、快速的、强大的、灵活的、可扩展的、直观的、普遍适用的、具有良好的支持、没有使用约束、没有错误的。这也是不存在的。为尺寸和速度而进行优化的程序库一般不能被移植。具有大量功能的的程序库不会具有直观性。没有错误的程序库在使用范围上会有限制。真实的世界里,你不能拥有每一件东西,总得有付出。

不同的设计者给这些条件赋予了不同的优先级。他们从而在设计中牺牲了不同的东西。因此一般两个提供相同功能的程序库却有着完全不同的性能特征。

例如,考虑iostream和stdio程序库,对于C++程序员来说两者都是可以使用的。iostream程序库与C中的stdio相比有几个优点(参见Effective C++)。例如它是类型安全的(type-safe),它是可扩展的。然而在效率方面,iostream程序库总是不如stdio,因为stdio产生的执行文件与iostream产生的执行文件相比尺寸小而且执行速度快。

首先考虑执行速度的问题。要想掌握iostream和stdio之间的性能差别,一种方法就是用这两个程序库来运行benchmark程序。不过你必须记住benchmark也会撒谎。不仅很难拿出一组能够代表程序或程序库典型用法的数据,而且就算拿出来也是没用,除非有可靠的方法判断出你或你的客户的具有什么样的特征。不过在解决一个问题的不用方法的比较上,benchmark还是能够提供一些信息,所以尽管完全依靠benchmark是愚蠢的,但是忽略它们也是愚蠢的。

让我们测试一个简单的benchmark程序,只测试最基本的I/O功能。这个程序从标准输入读取30000个浮点数,然后把它们以固定的格式写到标准输出里。编译时预处理符号STDIO决定是使用stdio还是iostream。如果定义了这个符号,就是用stdio,否则就使用iostream程序库。

#ifdef STDIO

#include <stdio.h>

#else

#include <iostream>

#include <iomanip>

using namespace std;

#endif

 

 

const int VALUES = 30000;                 // # of values to read/write

 

int main()

{

  double d;

 

  for (int n = 1; n <= VALUES; ++n) {

#ifdef STDIO

    scanf("%lf", &d);

    printf("%10.5f", d);

#else

    cin >> d;

    cout  << setw(10)                     // 设定field宽度

          << setprecision(5)              // 设置小数位置

          << setiosflags(ios::showpoint)  // keep trailing 0s

          << setiosflags(ios::fixed)      // 使用这些设置

          << d;

#endif

 

    if (n % 5 == 0) {

#ifdef STDIO

      printf("/n");

#else

      cout << '/n';

#endif

    }

  }

 

  return 0;

}

当把正整数的自然对数传给这个程序,它会这样输出:

0.00000   0.69315   1.09861   1.38629   1.60944

1.79176   1.94591   2.07944   2.19722   2.30259

2.39790   2.48491   2.56495   2.63906   2.70805

2.77259   2.83321   2.89037   2.94444   2.99573

3.04452   3.09104   3.13549   3.17805   3.21888

这种输出至少表明了使用iostreams也能这种也能产生fixed-format I/O。当然,

cout  << setw(10)

      << setprecision(5)

      << setiosflags(ios::showpoint)

      << setiosflags(ios::fixed)

      << d;

远不如  printf("%10.5f", d); 输入方便。

但是操作符<<既是类型安全(type-safe)又可以扩展,而printf则不具有这两种优点。

我做了几种计算机、操作系统和编译器的不同组合,在其上运行这个程序,在每一种情况下都是使用stdio的程序运行得较快。优势它仅仅快一些(大约20%),有时则快很多(接近200%),但是我从来没有遇到过一种iostream的实现和与其相对应的stdio的实现运行速度一样快。另外,使用stdio的程序的尺寸比与相应的使用iostream的程序要小(有时是小得多)。(对于程序现实中的尺寸,这点差异就微不足道了)。

应该注意到stdio的高效性主要是由其代码实现决定的,所以我已经测试过的系统其将来的实现或者我没有测试过的系统的当前实现都可能表现出iostreamstdio并没有显著的差异。事实上,有理由相信会发现一种iostream的代码实现比stdio要快,因为iostream在编译时确定它们操作数的类型,而stdio的函数则是在运行时去解析格式字符串(format string)。iostreamstdio之间性能的对比不过是一个例子,这并不重要,重要的是具有相同功能的不同的程序库在性能上采取不同的权衡措施,所以一旦你找到软件的瓶颈(通过进行 profile 参见条款16),你应该知道是否可能通过替换程序库来消除瓶颈。比如如果你的程序有I/O瓶颈,你可以考虑用stdio替代iostream,如果程序在动态分配和释放内存上使用了大量时间,你可以想想是否有其他的operator new operator delete的实现可用(参见条款8Effective C++条款10)。因为不同的程序库在效率、可扩展性、移植性、类型安全和其他一些领域上蕴含着不同的设计理念,通过变换使用给予性能更多考虑的程序库,你有时可以大幅度地提高软件的效率。

 

阅读终点,创作起航,您可以撰写心得或摘录文章要点写篇博文。去创作
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
更有效的C指的是更有效地使用C语言编程的技巧和技术。C语言是一种古老但广泛使用的编程语言,它在系统级编程和高性能应用程序开发中具有广泛的应用。 首先,更有效的C编程意味着更优化的代码。程序员可以通过使用更高效的算法和数据结构来提高代码的性能。此外,还可以通过减少变量的使用、优化内存管理和减少函数调用等方式来提高代码的效率。 其次,更有效的C编程还包括更好的代码组织和结构。通过使用适当的模块化和抽象化技术,可以使代码更可读和可维护。良好的代码结构可以提高团队合作的效率,并减少错误和调试的时间。 另外,更有效的C编程也体现在更好的错误处理和异常处理机制。通过正确处理错误和异常,可以提高程序的健壮性和可靠性。这包括使用适当的错误代码和错误消息来有效地调试和定位问题。 此外,编写高效的C代码还需要充分利用编译器的优化功能。通过了解编译器的工作原理和使用适当的编译选项,可以提高代码的执行速度和运行效率。 最后,更有效的C编程还需要注重维护和优化代码。程序员需要根据需求和反馈周期性地进行代码优化和重构。这可以帮助改进代码的可读性、可维护性和性能。 总的来说,更有效的C编程意味着更优化的代码、更好的代码组织和结构、更好的错误处理和异常处理、充分利用编译器的优化功能以及定期的代码维护和优化。通过这些技术和实践,可以提高C编程的效率和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值