質問

そうのように見えるかもしれませんが、実際にはこれはデザインの問題ではありません。(まあ、それはデザインの問題のようなものです)。私が疑問に思っているのは、なぜ C++ なのかということです。 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 可能な限り?

役に立ちましたか?

解決

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と一緒です fstreams.また、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
}

どちらの方法でも変換できるため、 std::string および呼び出し先の C 文字列 f() 2 つのどちらかに解決される可能性があります f() 選択肢があるため、曖昧です。解決策は、1 つの変換方向を明示的にすることで変換サイクルを断ち切ることです。これが STL が選択したことです。 c_str().

他のヒント

C++ 標準委員会が標準ライブラリ内の機能間の相互作用を実際には最適化していない場所がいくつかあります。

std::string 図書館での使用もその 1 つです。

もう一つの例は、 std::swap. 。多くのコンテナーには swap メンバー関数がありますが、std::swap のオーバーロードは提供されていません。同じことが当てはまります std::sort.

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

おそらくそれは慰めになるでしょう:C++0x 標準の草案では、すべての fstream が open(char const *, ...) の隣に open(string const &, ...) を取得しています。(例を参照)Basic_ifstream 宣言の場合は 27.8.1.6)

したがって、それが完成して実装されると、もう手に入れることはできません:)

ストリーム IO ライブラリは、STL よりも前に標準 C++ ライブラリに追加されました。下位互換性を失わないために、たとえそれがあなたが提起したような問題を意味するとしても、STL が追加されたときに IO ライブラリを変更しないことが決定されました。

@バーナード:
モノリス「Unstrung」。 「すべてが1つ、1つはすべて」マスケット銃選手にとっては機能するかもしれませんが、クラスデザイナーにとってはほとんど機能しません。以下の例は、まったく模範的ではありませんが、設計が過剰設計になると、どれほどひどい間違いを犯す可能性があるかを示しています。残念ながら、この例は近くの標準図書館から抜粋したものです...~ http://www.gotw.ca/gotw/084.htm

それはどうでもいいことです、それは本当です。std::string のインターフェイスが大きいとはどういう意味ですか?この文脈では、「大量のメソッド呼び出し」とは何を意味するのでしょうか?冗談ではなく、実際に興味があります。

これには実際に必要なメソッドよりも多くのメソッドがあり、反復子ではなく整数オフセットを使用する動作は少し不確かです (ライブラリの残りの部分の動作方法に反しているため)。

私が思う本当の問題は、C++ ライブラリには 3 つの部分があるということです。古い C ライブラリ、STL、文字列と iostream があります。さまざまな部分を橋渡しするためにいくつかの努力が払われましたが(例:C++ はオーバーロードをサポートしているため、C ライブラリにオーバーロードを追加します。Basic_string への反復子の追加。iostream イテレータ アダプタの追加など)、詳細を見ると多くの不一致があります。

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

C++ は、今日私たちがコードを書くモンスターよりも小さなマシンで育ちました。iostream が新しい頃、多くの開発者はコード サイズを非常に気にしていました (プログラム全体とデータを数百 KB に収める必要がありました)。したがって、多くの人は「大きな」C++ 文字列ライブラリを取り込みたくありませんでした。多くの人は、コードサイズという同じ理由で、iostream ライブラリを使用さえしませんでした。

現在のように、何千メガバイトもの RAM を使い回すことはできませんでした。通常、関数レベルのリンクはなかったので、ライブラリの開発者のなすがままに、多数の個別のオブジェクト ファイルを使用するか、あるいは大量の呼び出されていないコードを取り込むことになりました。こうした FUD のすべてにより、開発者は std::string から遠ざかるようになりました。

当時は std::string も避けていました。「肥大化しすぎる」、「malloc を頻繁に呼び出す」など。愚かにも文字列にスタックベースのバッファを使用し、オーバーランしないようにあらゆる種類の退屈なコードを追加します。

STLには文字列を受け取るクラスはありますか...私はそうは思いません(簡単な検索では見つかりませんでした)。したがって、STL のクラスは他の STL クラス (機能に直接必要ではない) に依存すべきではないという設計上の決定がおそらく行われます。

これは依存性を避けるために考えられ、行われたものだと思います。つまり#include <fstream> は #include <string> を強制すべきではありません。

正直に言うと、これは非常に重要ではない問題のように思えます。もっと良い質問は、std::string のインターフェイスがなぜこれほど大きいのかということです。

現在、この問題は非常に簡単に解決できます。追加 -std=c++11 あなたへ CFLAGS.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top