(Effective C++学习笔记)条款 2:尽量用<iostream>而不用<stdio.h>

10/26 11:48
阅读数 22

条款 2:尽量用<iostream>而不用<stdio.h>

  • scanf printf 很轻巧,很高效,事实上 scanf printf 及其系列还可以做些改进,他们不是类型安全的,而且没有扩展性。因为类型安全和扩展性是 C++基石,所以也要服从这一点。
  • scanf/printf 系列函数把要读写的变量和控制读写格式的信息分开来,就象古老的 FORTRAN 那样,scanf/printf 的这些弱点正是操作符>><<的强项:
int i;
Rational r; // r 是个有理数
...
cin >> i >> r;
cout << i << r;
  • 上面的代码要通过编译,>><<必须是可以处理 Rational 类型对象的重载函数(可能要通过隐式类型转换)
  • 如果没有实现这样的函数,就会出错(处理 int不用这样做,因为它是标准用法)
  • 编译器自己可以根据不同的变量类型选择操作符的不同形式,所以不必劳你去指定第一个要读写的对象是 int 而第二个是 Rational
  • 在传递读和写的对象时采用的语法形式相同,所以不必象 scanf 样死记一些规定,比如如果没有得到指针,必须加上地址符,而如果已经得到了指针,又要确定不要加上地址符。这些完全可以交给 C++编译器去做。编译器没别的什么事好做的,而你却不一样。最后要注意的是,象 int 这样的固定类型和象 Rational这样的自定义类型在读写时方式是一样的。
  • 所写的表示有理数的类的代码可能象下面这样:
class Rational {
public:
	Rational(int numerator = 0, int denominator = 1);
	...
private:
	int n, d; // 分子,分母
	friend ostream& operator<<(ostream& s, const Rational& r);
};
ostream& operator<<(ostream& s, const Rational& r)
{
	s << r.n << '/' << r.d;
	return s;
}
  • 上面的代码涉及到 operator<<的一些微妙(但很重要)的用法
    • 例如:上面的 operator<<不是成员函数(条款 19 解释了为什),而且,传递给 operator<<的不是 Rational 对象,而是定义为 const 的对象的引用(参见条款 22)operator>>的声明和实现也类似。
  • 有些情况下回到那些经过证明而且正确的老路上去还是很有意义的
    • 第一,有些 iostream 的操作实现起来比相应的 C stream效率要低,所以不同的选择会给你的程序有可能(虽然不一定,参见条款 M16)带来很大的不同。但请牢记,这不是对所有的 iostream 而言,只是一些特殊的实现;参见条款 M23
    • 第二,在标准化的过程中,iostream 库在底层做了很多修改(参见条款 49),所以对那些要求最大可移植性的应用程序来说,会发现不同的厂商遵循标准的程度也不同。
    • 第三,iostream 库的类有构造函数而里的函数没有,在某些涉及到静态对象初始化顺序的时候,如果可以确认不会带来隐患,用标准 C 库会更简单实用。
  • iostream 库的类和函数所提供的类型安全和可扩展性的价值远远超过你当初的想象,所以不要仅仅因为用惯了而舍弃它。毕竟,转换到 iostream后,也不会忘掉。
  • 其实没有<iostream.h>这样的东西——标准化委员会在简化非 C 标准头文件时用<iostream>取代了它。
    • 他们这样做的原因在条款 49 进行了解释。还必须知道的是,如果编译器同时支持 <iostream>和<iostream.h> ,那头文件名的使用会很微妙。
    • 例如,如果使用了 #include<iostream>, 得到的是置于名字空间 std(见条款 28)下的 iostream 库的元素;如果使用#include <iostream.h>,得到的是置于全局空间的同样的元素。在全局空间获取元素会导致名字冲突,而设计名字空间的初衷正是用来避免这种名字冲突的发生。还有,打字时<iostream>比<iostream.h>少两个字,这也是很多人用它的原因。
  • 【注】参考《Effective C++》
展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
OSCHINA
登录后可查看更多优质内容
返回顶部
顶部