2008-08-28 76 views
34

這不是一個設計問題,確實如此,儘管看起來可能如此。 (好吧,這是一個設計問題)。我想知道的是爲什麼C++ std::fstream類不在其構造函數或開放方法中使用std::string。每個人都喜歡這樣的代碼示例:爲什麼std :: fstream類不需要std :: string?

#include <iostream> 
#include <fstream> 
#include <string> 

int main() 
{ 
    std::string filename = "testfile";  
    std::ifstream fin; 

    fin.open(filename.c_str()); // Works just fine. 
    fin.close(); 

    //fin.open(filename); // Error: no such method. 
    //fin.close(); 
} 

這使我一直處理文件。只要有可能,C++庫肯定會使用std::string

回答

26

通過取一個C字符串,C++ 03 std::fstream類減少了對std::string類的依賴。然而,在C++ 11中,std::fstream類允許傳遞std::string作爲其構造函數參數。現在

,你可能會問,爲什麼沒有從std:string透明轉換爲C字符串,這樣一類需要一個C字符串仍然可以採取std::string就像期望一個std::string可以採取一個C類串。

原因是這會導致轉換週期,反過來可能會導致問題。例如,假設std::string可以轉換爲C字符串,以便您可以使用std::string s和fstream s。假設C字符串可以轉換爲std::strings,就像當前標準中的狀態一樣。現在,考慮以下因素:

void f(std::string str1, std::string str2); 
void f(char* cstr1, char* cstr2); 

void g() 
{ 
    char* cstr = "abc"; 
    std::string str = "def"; 
    f(cstr, str); // ERROR: ambiguous 
} 

因爲你可以任一方式轉換std::string和C字符串調用f()能夠解決到兩個f()的替代品,因此是模棱兩可之間。解決方案是通過明確一個轉換方向來打破轉換週期,這是STL選擇使用c_str()所做的選擇。

+1

該示例不應對重載解析規則造成任何歧義。 `f(char *,std :: string)`是[精確匹配](http://www.lcdf.org/c++/clause13.html#s13.3.3.1.1),而其他的則需要轉換,因此首先是最好的可行功能。如果你刪除了第一個`f`,那麼就像[(char *&,std :: string&) - >(char *,std :: string) - >(char *,char *))[更好的轉換序列](http://www.lcdf.org/c++/clause13.html#s13.3.3)比「(char *&,std :: string&) - >(char *,std :: string) - >(std: :string,char *)「,第二個`f`將是最好的可行函數。我錯過了什麼嗎? – outis 2010-11-14 23:49:43

0

STL中是否有需要字符串的類...我不這麼認爲(在我的快速搜索中找不到任何類)。所以這可能是一些設計決定,STL中的任何類都不應該依賴於任何其他STL類(這不是功能直接需要的)。

14

有幾個地方C++標準委員會沒有真正優化標準庫中設施之間的交互。

std::string它在圖書館中的使用就是其中之一。

另一個例子是std::swap。許多容器都具有交換成員函數,但不提供std :: swap的重載。 std::sort也是如此。

我希望所有這些小東西都會在即將到來的標準中得到解決。

0

我相信這已經被考慮過,並且是爲了避免依賴;即#include <fstream>不應強制#include <字符串>。

說實話,這似乎是一個相當不重要的問題。更好的問題是,爲什麼std :: string的界面如此之大?

2

這是不重要的,那是真的。 std :: string的接口很大是什麼意思?在這種情況下,大的含義是什麼 - 大量的方法調用?我並不是一個人,我真的很感興趣。

它有比實際需要更多的方法,它使用積分偏移而不是迭代器的行爲有點不確定(因爲它與庫的其餘部分的工作方式相反)。

我認爲真正的問題是C++庫有三個部分;它有舊的C庫,它有STL,它有字符串和iostreams。儘管已經做了一些工作來彌補不同的部分(例如,爲C庫添加了重載,因爲C++支持重載;向basic_string添加迭代器;添加了iostream迭代器適配器),但是當您存在很多不一致時看看細節。

例如,basic_string包括標準算法不必要的重複方法;各種查找方法,可能可以安全地刪除。另一個例子:語言環境使用原始指針而不是迭代器。

3

@ Bernard:
Monoliths「Unstrung」。 「一切爲了所有人」可能適用於火槍手,但對於班級設計師來說,這種方式幾乎沒有效果。下面是一個不完全示範的例子,它說明了當設計變成過度設計時,你會錯多少。這個例子是,不幸的是,從你附近的一個標準庫取... 〜http://www.gotw.ca/gotw/084.htm

11

也許這是一個安慰:所有的fstream的已經得到了一個開放的(字符串常量&,...)旁開(字符常量*,...)在C++ 0x標準的工作草案中。 (例如參見27.8.1.6爲basic_ifstream聲明)

因此,當它被敲定並執行,就不會得到你了:)

9

流IO庫已被添加到C++標準庫前STL。爲了不破壞向後兼容性,已經決定避免在添加STL時修改IO庫,即使這意味着您提出的問題。

1

C++在小型機器上長大,比我們今天編寫代碼的怪物長大。當iostream是新的時候,許多開發人員真的關心代碼大小(他們必須將他們的整個程序和數據放入幾百KB)。因此,許多人不想拉入「大」的C++字符串庫。許多人甚至沒有使用iostream庫的代碼大小相同的原因。

我們沒有像現在這樣做的數千兆內存。我們通常沒有函數級鏈接,因此我們受庫開發人員的束縛,無法使用大量單獨的對象文件,或者引入大量未調用的代碼。所有這些FUD都使開發人員避開了std :: string。

那時我回避了std :: string。 「太臃腫」,「過於頻繁地調用malloc」等。愚蠢地使用基於堆棧的緩衝區來處理字符串,然後添加各種繁瑣的代碼以確保它不會溢出。

0

現在,您可以非常輕鬆地解決此問題:將-std=c++11添加到您的CFLAGS

相關問題