- 论坛徽章:
- 0
|
Google C++编程风格指南
流(Streams):只在记录日志时使用流。
定义:
流是printf()和scanf()的替代。
优点:
有了流,在输出时不需要关心对象的类型,不用担心格式化字符串与参数列表不匹配(虽然在gcc中使用printf也不存在这个问题),打开、关闭对应文件时,流可以自动构造、析构。
缺点:
流使得pread()等功能函数很难执行,如果不使用printf之类的函数而是使用流很难对格式进行操作(尤其是常用的格式字符串%.*s),流不支持字符串操作符重新定序(%1s),而这一点对国际化很有用。
结论:
不要使用流,除非是日志接口需要,使用printf之类的代替。使用流还有很多利弊,代码一致性胜过一切,不要在代码中使用流。
拓展讨论:
对这一条规则存在一些争论,这儿给出深层次原因。回忆唯一性原则(Only One Way):我们希望在任何时候都只使用一种确定的I/O类型,使代码在所有I/O处保持一致。因此,我们不希望用户来决定是使用流还是printf + read/write,我们应该决定到底用哪一种方式。把日志作为例外是因为流非常适合这么做,也有一定的历史原因。
使用流易造成的错误:
流的支持者们主张流是不二之选,但观点并不是那么清晰有力,他们所指出流的所有优势也正是其劣势所在。流最大的优势是在输出时不需要关心输出对象的类型,这是一个亮点,也是一个不足:很容易用错类型,而编译器不会报警。使用流时容易造成的一类错误是:
- cout << this; // Prints the address
- cout << *this; // Prints the contents
复制代码
编译器不会报错,因为<<被重载,就因为这一点我们反对使用操作符重载。
可读性比较:
有人说printf的格式化丑陋不堪、易读性差,但流也好不到哪儿去。看看下面两段代码吧,哪个更加易读?
- cerr << "Error connecting to '" << foo->bar()->hostname.first
- << ":" << foo->bar()->hostname.second << ": " << strerror(errno);
复制代码
- fprintf(stderr, "Error connecting to '%s:%u: %s",
- foo->bar()->hostname.first, foo->bar()->hostname.second, strerror(errno));
复制代码
你可能会说,“把流封装一下就会比较好了”,这儿可以,其他地方呢?而且不要忘了,我们的目标是使语言尽可能小,而不是添加一些别人需要学习的新的内容。
总结:
每一种方式都是各有利弊,“没有最好,只有更好”,简单化的教条告诫我们必须从中选择其一,最后的多数决定是printf + read/write。
[ 本帖最后由 CRLF 于 2009-2-9 13:46 编辑 ] |
|