iostream与iostream.h的区别详细解析

时间:2022-06-15 07:16:33

C++的标准类库被修订了两次,有两个标准 C92和C99,这两个库现在都在并行使用,用 .h 包含的是c92 ,不带 .h 的是c99的头文件,对于普通用户来说这两者没有什么区别,区别是在内部函数的具体实现上。旧的C++头文件是官方明确反对使用的,但旧的C头文件则没有(以保持对C的兼容性)。据说从 Visual C++ .NET 2003 开始,移除了旧的 iostream 库。其实编译器制造商不会停止对客户现有软件提供支持,所以在可以预计的将来,旧的C++头文件还会嚣张一段时间。如果能明白字符串头文件的使用,举一反三,其他的也差不多会用了:

<string.h>是旧的C/C++头文件,对应的是基于char*的字符串处理函数;
<string>是包装了std的C++头文件,对应的是新的strng类;
<cstring>是对应旧的C头文件的std版本。

如果编译器都同时支持< iostream >和< iostream.h >,那使用#include < iostream >,得到的是置于名字空间std下的iostream库的元素;如果使用#include < iostream.h >,得到的是置于全局空间的同样的元素。在全局空间获取元素会导致名字冲突,而设计名字空间的初衷正是用来避免这种名字冲突的发生。

想象讯雷下载软件一样,先从服务器确定下载文件的大小,初始时即保存文件,全部填充0,多个线程下载数据直接写入文件,对自己线程负责下载的那段文件片的0进行改写,其中就涉及到文件共享写的操作

出现的问题时:
vc7.1<fstream> 已经不支持 filebuf::sh_read等关键字,不知在vc7下若要用文件流来对文件进行非独占读和写操作该如何实现?

而:
vc6.0中的iostream.h <fstream.h>
filebuf::sh_read
filebuf::sh_write
filebuf::sh_note
filebuf::sh_openprot

无论自己是用vc6或者vc7的IDE
当用到标准的输入输出和文件流时都是:
include<iostream>
include<fstream>
using namespace std;


有两种用法:
A:
include<iostream.h>
include<fstream.h>

B:
include<iostream>
include<fstream>

A是标准用法,B是老式用法。
如果用了<iostream>,则一定要引入命名空间,即"using namespace std;".
如果用了<iostream.h>,则不那引入命名空间,否则会引起编译错误,提示找不到命名空间,例程如下:

//情况一:使用<iostream>和命名空间
#include <iostream>
using namespace std;
int main()
{
cout<<"<iostream> need to use namespace std!/n";
return 0;
}
输出:
<iostream> need to use namespace std!
Press any key to continue

//情况二:使用<iostream.h>,不引入命名空间
#include <iostream.h>
//using namespace std;
int main()
{
cout<<"<iostream> need to use namespace std!/n";
return 0;
}
输出:
<iostream> need to use namespace std!
Press any key to continue

//情况三:使用<iostream.h>,引入命名空间,这时候编译出错
#include <iostream.h>
using namespace std;
int main()
{
cout<<"<iostream> need to use namespace std!/n";
return 0;
}
编译错误信息:
error C2871: 'std' : does not exist or is not a namespace

从 Visual C++ .NET 2003 开始,移除了旧的 iostream 库。
标准 C++ 库和以前的运行时库之间的主要差异在于 iostream 库。iostream 实现的具体细节已经更改,如果想链接标准 C++ 库,可能有必要重写代码中使用 iostream 的部分。
必须移除任何包含在代码中的旧 iostream 头文件(fstream.h、iomanip.h、ios.h、iostream.h、istream.h、ostream.h、streamb.h 和 strstrea.h),并添加一个或多个新的标准 C++ iostream 头文件(<fstream>、<iomanip>、<ios>、<iosfwd>、<iostream>、<istream>、<ostream>、<sstream>、<streambuf> 和 <strstream>,所有头文件都没有 .h 扩展名)。
下表描述新的标准 C++ iostream 库不同于旧 iostream 库的行为。

在新的标准 C++ iostream 库中:
open 函数不采用第三个参数(保护参数)。
无法从文件句柄创建流。
除了几个例外,新的标准 C++ 库中的所有名称都在 std 命名空间中。有关更多信息,请参见使用 C++ 库头。
单独用 ios::out 标志无法打开 ofstream 对象。ios::out 标志必须在逻辑 OR 中和另一个 ios 枚举数组合;比如,和 ios::in 或 ios::app 组合。
因为设置了 eofbit 状态,到达文件尾后 ios::good 不再返回非零值。
除非知道当前没有设置基标志,否则 ios::setf(_IFlags) 不应和 ios::dec、ios::oct 或 ios::hex 的标志值一起使用。格式化的输入/输出函数和运算符假定只设置了一个基。改用 ios_base。例如,setf( ios_base::oct, ios_base::basefield ) 清除所有基信息并将基设置成八进制。
ios::unsetf 返回 void 而不是以前的值。
若出现错误,istream::get( char& _Rch ) 不分配给 Rch。
istream::get( char* _Pch, int _Ncount, char _Delim ) 有三点不同:
没读取任何内容时设置 failbit。
提取的字符后总是存储一个 eos(与结果无关)。
值为 -1 时 _Ncount 是一个错误。
具有无效参数的 istream::seekg 不设置 failbit。
返回类型 streampos 是具有重载运算符的类。在返回 streampos 值(比如 istream::tellg、ostream::tellp、strstreambuf::seekoff 和 strstreambuf::seekpos)的函数中,应将返回值转换成所需的类型:streamoff、fpos_t 或 mbstate_t。
strstreambuf::strstreambuf( _Falloc, _Ffree ) 中的第一个函数参数采用 size_t 参数而不是 long。

除了上述改动外,以下作为旧 iostream 库元素的函数、常数和枚举数不是新 iostream 库的元素:
filebuf、fstream ifstream 和 ofstream 的 attach 成员函数
filebuf、fstream ifstream 和 ofstream 的 fd 成员函数
filebuf::openprot
filebuf::setmode
ios::bitalloc
ios::nocreate
ios::noreplace
ios::sync_with_stdio
streambuf::out_waiting
streambuf::setbuf(相同的行为使用 rdbuf -> pubsetbuf)

STL FAQ 上有对标准库用法的一些建议,在《软件研发》杂志上也有这方面的讨论的文章,可惜,这么好的杂志也停刊了(可能上面的知识对中国的程序员太过超前了,别人说的,奇怪,我怎么看得明白了).

What's the difference between <xxx> and <xxx.h> headers

The headers in ISO Standard C++ don't have a .h suffix. This is something the standards committee changed from former practice. The details are different between headers that existed in C and those that are specific to C++.

The C++ standard library is guaranteed to have 18 standard headers from the C language. These headers come in two standard flavors, <cxxx> and <xxx.h> (where xxx is the basename of the header, such as stdio, stdlib, etc). These two flavors are identical except the <cxxx> versions provide their declarations in the std namespace only, and the<xxx.h> versions make them available both in std namespace and in the global namespace. The committee did it this way so that existing C code could continue to be compiled in C++. However the <xxx.h> versions are deprecated, meaning they are standard now but might not be part of the standard in future revisions. (See clause D.5 of the ISO C++ standard.)

The C++ standard library is also guaranteed to have 32 additional standard headers that have no direct counterparts in C, such as <iostream>, <string>, and <new>. You may see things like #include <iostream.h> and so on in old code, and some compiler vendors offer .h versions for that reason. But be careful: the .h versions, if available, may differ from the standard versions. And if you compile some units of a program with, for example, <iostream> and others with <iostream.h>, the program may not work.

For new projects, use only the<xxx> headers, not the<xxx.h> headers.

When modifying or extending existing code that uses the old header names, you should probably follow the practice in that code unless there's some important reason to switch to the standard headers (such as a facility available in standard<iostream> that was not available in the vendor's <iostream.h>). If you need to standardize existing code, make sure to change all C++ headers in all program units including external libraries that get linked in to the final executable.

All of this affects the standard headers only. You're free to name your own headers anything you like; see [27.9].

标准库扩展了原库,例如新库<string>还支持宽字符集的操作,所以我认为在现在大多数的编译器都已支持标准C++的情况下,所有的程序都应该使用标准头文件的导入方式!

对于名字空间 namespace std 的使用,C++ 的 FAQ 的回答是这样的

Should I use using namespace std in my code?

Probably not.

People don't like typing std:: over and over, and they discover that using namespace std lets the compiler see any std name, even if unqualified. The fly in that ointment is that it lets the compiler see any std name, even the ones you didn't think about. In other words, it can create name conflicts and ambiguities.

For example, suppose your code is counting things and you happen to use a variable or function named count. But the std library also uses the name count (it's one of the std algorithms), which could cause ambiguities.

Look, the whole point of namespaces is to prevent namespace collisions between two independently developed piles of code. The using-directive (that's the technical name for using namespace XYZ) effectively dumps one namespace into another, which can subvert that goal. The using-directive exists for legacy C++ code and to ease the transition to namespaces, but you probably shouldn't use it on a regular basis, at least not in your new C++ code.

If you really want to avoid typing std::, then you can either use something else called a using-declaration, or get over it and just type std:: (the un-solution):

Use a using-declaration, which brings in specific, selected names. For example, to allow your code to use the name cout without a std:: qualifier, you could insert using std::cout into your code. This is unlikely to cause confusion or ambiguity because the names you bring in are explicit.

复制代码 代码如下:


just type std:: (the un-solution):
 #include <vector>
 #include <iostream>

 void f(const std::vector<double>& v)
 {
 using std::cout;// ← a using-declaration that lets you use cout without qualification

 cout << "Values:";
 for (std::vector<double>::const_iterator p = v.begin(); p != v.end(); ++p)
 cout << ' ' << *p;
 cout << '/n';
 }
 

 

Get over it and

 #include <vector>
 #include <iostream>

 void f(const std::vector<double>& v)
 {
 std::cout << "Values:";
 for (std::vector<double>::const_iterator p = v.begin(); p != v.end(); ++p)
 std::cout << ' ' << *p;
 std::cout << '/n';
 }


I personally find it's faster to type "std::" than to decide, for each distinct std name, whether
or not to include a using-declaration and if so, to find the best scope and add it there. But
either way is fine. Just remember that you are part of a team, so make sure you use an approach
that is consistent with the rest of your organization.