2008-08-28 19 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を渡すことができます。

さて、あなたは不思議に思うかもしれなぜC文字列にstd:stringから透明の変換が存在しないので、Cの文字列を期待していたクラスがまだちょうどstd::stringはCを取ることができます期待していたクラスのようなstd::stringを取ることができます文字列。

これは、これが変換サイクルを引き起こし、その結果問題につながる可能性があるためです。たとえば、std::stringstd::stringfstreamを使用できるように、C文字列に変換できるとします。現在の標準の状態と同様に、C文字列がstd::stringに変換可能であるとします。さて、次の点を考慮してください

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 
} 

あなたはf()への呼び出しが2つのf()の選択肢のいずれかに解決できstd::stringとC文字列の間のいずれかの方法を変換するため、曖昧である可能性があるため。解決方法は、1つの変換方向を明示的にすることによって変換サイクルを中断することです。これは、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 *) "は[より良い変換シーケンス"(char *、std :: string) - >(std:string) - >(char *、std :: string) - >(char *、std :: string)よりも(http://www.lcdf.org/c++/clause13.html#s13.3.3) :string、char *) "、第2の' f'が実行可能な関数として最適です。何か不足していますか? – outis

+0

私は遅れていましたが、修正されました。 – wilhelmtell

+2

このマイクロ最適化は、(1)文字列が言語のあらゆる構成要素、特に文字列と緊密に結合されていること(これは 'GMP'が短絡に依存しないようにすることに似ています) 2) 'char *'は邪悪なものです。ユーザーが使用することを奨励すべきではありません。また、コンパイル時にはミリ秒で十分です。最後に(3) ' '私はデカップリングの依存関係は、この場合の正当な理由ではないと主張しています。 –

0

文字列を取るSTLのクラスはありますか?私はそうは思わない(私のクイック検索では何も見つかりませんでした)。したがって、STLのどのクラスも他のSTLクラス(それは機能には直接必要ではない)に依存してはならないという設計上の決定になるでしょう。

14

C++標準委員会が実際に標準ライブラリの施設間のやりとりを最適化しなかった場所がいくつかあります。

std::stringであり、ライブラリーにおけるその使用は、これらのうちの1つである。

もう1つの例はstd::swapです。多くのコンテナには、スワップメンバ関数がありますが、std :: swapのオーバーロードはありません。 std::sortも同様です。

これらの小さなものすべてが今後の標準で修正されることを願っています。

0

私はこれが考えられており、依存関係を避けるために行われたと信じています。すなわち#include <fstream>は、#を<の文字列>を含む#に強制しません。

正直言って、これはかなり重要ではないようです。より良い質問は、std :: stringのインターフェースがとても大きいのはなぜですか?

2

これは事実ではありません。 std :: stringのインターフェイスが大きくなっているとはどういう意味ですか?この文脈で大規模な意味は何ですか?メソッド呼び出しがたくさんありますか?私は面倒ではない、私は実際に興味がある。

これは本当に必要な方法が多く、イテレータよりも積分オフセットを使用する方法が少し複雑です(ライブラリの残りの仕組みとは逆です)。

本当の問題は、C++ライブラリには3つの部分があることです。それは古いCライブラリを持ち、それはSTLを持っていて、文字列とiostreamを持っています。 C++はオーバーロードをサポートしているため、オーバーロードをCライブラリに追加する、イテレータをbasic_stringに追加する、iostreamイテレータ・アダプタを追加するなどの)さまざまな部分をブリッジするためにいくつかの努力が行われましたが、詳細を見てください。

たとえば、basic_stringには標準アルゴリズムの不要な複製であるメソッドが含まれています。おそらく、さまざまな検索方法は、おそらく安全に削除することができます。別の例:ロケールはイテレータの代わりに生ポインタを使用します。

3

@バーナード:
モノリス "Unstrung。" "1人、すべての人のためのすべて"は兵士のために働くかもしれませんが、クラスデザイナーにとってはほとんどうまく機能しません。これはあくまでも例ではありませんが、デザインが過度に設計されたときに間違っていける可能性を示しています。たとえば、残念ながら、お近くの標準ライブラリから取得されます...〜http://www.gotw.ca/gotw/084.htm

11

は、多分それは慰めです:すべてのfstreamのは、オープン(char型のconstの隣にオープン(文字列のconst &を、...)を得ています*、...)C++ 0x標準の作業草案では、 (basic_ifstream宣言に対して例えば27.8.1.6を参照)

それが確定して実装されますときに、それはもうあなたを取得することはありません:)

9

ストリームIOライブラリを前に、標準C++ライブラリに追加されましたSTL。下位互換性を損なわないために、STLを追加したときにIOライブラリを変更しないようにしました。

1

C++は今日のコードを書くモンスターよりも小さなマシンで育った。 iostreamが新しくなったとき、多くの開発者は実際にコードサイズを気にしていました(プログラムやデータを数百KBに収める必要がありました)。そのため、多くの人は "大きな" C++文字列ライブラリを取り入れたくありませんでした。多くの人が同じ理由、コード・サイズでiostreamライブラリーを使用していませんでした。

今日のように、数千メガバイトのRAMがありませんでした。私たちは通常、関数レベルのリンクを持っていなかったので、ライブラリの開発者がたくさんの別々のオブジェクトファイルを使用するか、それとも呼び出されていないコードをたくさん引っ張っていたのです。このFUDのすべては、開発者をstd :: stringから遠ざけるようにしました。

私はstd :: stringも避けました。 "あまりにも肥大化"、 "mallocと呼ばれることが多い"など。愚かなことに、スタックベースのバッファを文字列に使用し、すべての種類の面倒なコードを追加してオーバーランしないようにします。

0

最近では、この問題を非常に簡単に解決できます。CFLAGS-std=c++11を追加してください。

関連する問題