iostream與iostream.h的區(qū)別詳細(xì)解析
C++的標(biāo)準(zhǔn)類庫(kù)被修訂了兩次,有兩個(gè)標(biāo)準(zhǔn) C92和C99,這兩個(gè)庫(kù)現(xiàn)在都在并行使用,用 .h 包含的是c92 ,不帶 .h 的是c99的頭文件,對(duì)于普通用戶來說這兩者沒有什么區(qū)別,區(qū)別是在內(nèi)部函數(shù)的具體實(shí)現(xiàn)上。舊的C++頭文件是官方明確反對(duì)使用的,但舊的C頭文件則沒有(以保持對(duì)C的兼容性)。據(jù)說從 Visual C++ .NET 2003 開始,移除了舊的 iostream 庫(kù)。其實(shí)編譯器制造商不會(huì)停止對(duì)客戶現(xiàn)有軟件提供支持,所以在可以預(yù)計(jì)的將來,舊的C++頭文件還會(huì)囂張一段時(shí)間。如果能明白字符串頭文件的使用,舉一反三,其他的也差不多會(huì)用了:
<string.h>是舊的C/C++頭文件,對(duì)應(yīng)的是基于char*的字符串處理函數(shù);
<string>是包裝了std的C++頭文件,對(duì)應(yīng)的是新的strng類;
<cstring>是對(duì)應(yīng)舊的C頭文件的std版本。
如果編譯器都同時(shí)支持< iostream >和< iostream.h >,那使用#include < iostream >,得到的是置于名字空間std下的iostream庫(kù)的元素;如果使用#include < iostream.h >,得到的是置于全局空間的同樣的元素。在全局空間獲取元素會(huì)導(dǎo)致名字沖突,而設(shè)計(jì)名字空間的初衷正是用來避免這種名字沖突的發(fā)生。
想象訊雷下載軟件一樣,先從服務(wù)器確定下載文件的大小,初始時(shí)即保存文件,全部填充0,多個(gè)線程下載數(shù)據(jù)直接寫入文件,對(duì)自己線程負(fù)責(zé)下載的那段文件片的0進(jìn)行改寫,其中就涉及到文件共享寫的操作
出現(xiàn)的問題時(shí):
vc7.1<fstream> 已經(jīng)不支持 filebuf::sh_read等關(guān)鍵字,不知在vc7下若要用文件流來對(duì)文件進(jìn)行非獨(dú)占讀和寫操作該如何實(shí)現(xiàn)?
而:
vc6.0中的iostream.h <fstream.h>
filebuf::sh_read
filebuf::sh_write
filebuf::sh_note
filebuf::sh_openprot
無論自己是用vc6或者vc7的IDE
當(dāng)用到標(biāo)準(zhǔn)的輸入輸出和文件流時(shí)都是:
include<iostream>
include<fstream>
using namespace std;
有兩種用法:
A:
include<iostream.h>
include<fstream.h>
B:
include<iostream>
include<fstream>
A是標(biāo)準(zhǔn)用法,B是老式用法。
如果用了<iostream>,則一定要引入命名空間,即"using namespace std;".
如果用了<iostream.h>,則不那引入命名空間,否則會(huì)引起編譯錯(cuò)誤,提示找不到命名空間,例程如下:
//情況一:使用<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>,引入命名空間,這時(shí)候編譯出錯(cuò)
#include <iostream.h>
using namespace std;
int main()
{
cout<<"<iostream> need to use namespace std!/n";
return 0;
}
編譯錯(cuò)誤信息:
error C2871: 'std' : does not exist or is not a namespace
從 Visual C++ .NET 2003 開始,移除了舊的 iostream 庫(kù)。
標(biāo)準(zhǔn) C++ 庫(kù)和以前的運(yùn)行時(shí)庫(kù)之間的主要差異在于 iostream 庫(kù)。iostream 實(shí)現(xiàn)的具體細(xì)節(jié)已經(jīng)更改,如果想鏈接標(biāo)準(zhǔn) C++ 庫(kù),可能有必要重寫代碼中使用 iostream 的部分。
必須移除任何包含在代碼中的舊 iostream 頭文件(fstream.h、iomanip.h、ios.h、iostream.h、istream.h、ostream.h、streamb.h 和 strstrea.h),并添加一個(gè)或多個(gè)新的標(biāo)準(zhǔn) C++ iostream 頭文件(<fstream>、<iomanip>、<ios>、<iosfwd>、<iostream>、<istream>、<ostream>、<sstream>、<streambuf> 和 <strstream>,所有頭文件都沒有 .h 擴(kuò)展名)。
下表描述新的標(biāo)準(zhǔn) C++ iostream 庫(kù)不同于舊 iostream 庫(kù)的行為。
在新的標(biāo)準(zhǔn) C++ iostream 庫(kù)中:
open 函數(shù)不采用第三個(gè)參數(shù)(保護(hù)參數(shù))。
無法從文件句柄創(chuàng)建流。
除了幾個(gè)例外,新的標(biāo)準(zhǔn) C++ 庫(kù)中的所有名稱都在 std 命名空間中。有關(guān)更多信息,請(qǐng)參見使用 C++ 庫(kù)頭。
單獨(dú)用 ios::out 標(biāo)志無法打開 ofstream 對(duì)象。ios::out 標(biāo)志必須在邏輯 OR 中和另一個(gè) ios 枚舉數(shù)組合;比如,和 ios::in 或 ios::app 組合。
因?yàn)樵O(shè)置了 eofbit 狀態(tài),到達(dá)文件尾后 ios::good 不再返回非零值。
除非知道當(dāng)前沒有設(shè)置基標(biāo)志,否則 ios::setf(_IFlags) 不應(yīng)和 ios::dec、ios::oct 或 ios::hex 的標(biāo)志值一起使用。格式化的輸入/輸出函數(shù)和運(yùn)算符假定只設(shè)置了一個(gè)基。改用 ios_base。例如,setf( ios_base::oct, ios_base::basefield ) 清除所有基信息并將基設(shè)置成八進(jìn)制。
ios::unsetf 返回 void 而不是以前的值。
若出現(xiàn)錯(cuò)誤,istream::get( char& _Rch ) 不分配給 Rch。
istream::get( char* _Pch, int _Ncount, char _Delim ) 有三點(diǎn)不同:
沒讀取任何內(nèi)容時(shí)設(shè)置 failbit。
提取的字符后總是存儲(chǔ)一個(gè) eos(與結(jié)果無關(guān))。
值為 -1 時(shí) _Ncount 是一個(gè)錯(cuò)誤。
具有無效參數(shù)的 istream::seekg 不設(shè)置 failbit。
返回類型 streampos 是具有重載運(yùn)算符的類。在返回 streampos 值(比如 istream::tellg、ostream::tellp、strstreambuf::seekoff 和 strstreambuf::seekpos)的函數(shù)中,應(yīng)將返回值轉(zhuǎn)換成所需的類型:streamoff、fpos_t 或 mbstate_t。
strstreambuf::strstreambuf( _Falloc, _Ffree ) 中的第一個(gè)函數(shù)參數(shù)采用 size_t 參數(shù)而不是 long。
除了上述改動(dòng)外,以下作為舊 iostream 庫(kù)元素的函數(shù)、常數(shù)和枚舉數(shù)不是新 iostream 庫(kù)的元素:
filebuf、fstream ifstream 和 ofstream 的 attach 成員函數(shù)
filebuf、fstream ifstream 和 ofstream 的 fd 成員函數(shù)
filebuf::openprot
filebuf::setmode
ios::bitalloc
ios::nocreate
ios::noreplace
ios::sync_with_stdio
streambuf::out_waiting
streambuf::setbuf(相同的行為使用 rdbuf -> pubsetbuf)
STL FAQ 上有對(duì)標(biāo)準(zhǔn)庫(kù)用法的一些建議,在《軟件研發(fā)》雜志上也有這方面的討論的文章,可惜,這么好的雜志也停刊了(可能上面的知識(shí)對(duì)中國(guó)的程序員太過超前了,別人說的,奇怪,我怎么看得明白了).
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].
標(biāo)準(zhǔn)庫(kù)擴(kuò)展了原庫(kù),例如新庫(kù)<string>還支持寬字符集的操作,所以我認(rèn)為在現(xiàn)在大多數(shù)的編譯器都已支持標(biāo)準(zhǔn)C++的情況下,所有的程序都應(yīng)該使用標(biāo)準(zhǔn)頭文件的導(dǎo)入方式!
對(duì)于名字空間 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.
相關(guān)文章
關(guān)于C++對(duì)象繼承中的內(nèi)存布局示例詳解
這篇文章主要給大家介紹了關(guān)于C++對(duì)象繼承中內(nèi)存布局的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面跟著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08C語(yǔ)言實(shí)現(xiàn)BMP圖像的讀寫功能
這篇文章主要介紹了C語(yǔ)言實(shí)現(xiàn)BMP圖像的讀寫功能,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-04-04C++實(shí)現(xiàn)商店倉(cāng)庫(kù)管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)商店倉(cāng)庫(kù)管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03一篇文章帶你了解C語(yǔ)言的選擇結(jié)構(gòu)
這篇文章主要為大家介紹了C語(yǔ)言的選擇結(jié)構(gòu),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-01-01