36

これは設計上の問題ではありませんが、そのように思えるかもしれません。(まあ、それは一種の設計上の問題です)。私が疑問に思っているのは、なぜ 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可能な限り使用しますか?

4

10 に答える 10

26

C 文字列を取得することにより、C++03std::fstreamクラスはクラスへの依存を減らしましたstd::string。ただし、C++11 では、クラスのコンストラクター パラメーターにstd::fstreama を渡すことができます。std::string

ここで、なぜ a から C 文字列への透過的な変換がないのか疑問に思われるかもしれません。そのため、C 文字列を期待するクラスは、a を期待するクラスが C 文字列を受け取ることができるのと同じように、std:string依然として を受け取ることができます。std::stringstd::string

その理由は、これにより変換サイクルが発生し、問題が発生する可能性があるためです。たとえば、s を s とともにstd::string使用できるように、C 文字列に変換できるとします。また、現在の標準の状態のように、C 文字列が s に変換可能であるとします。ここで、次のことを検討してください。std::stringfstreamstd::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
}

と C 文字列の間でどちらの方法でも変換できるため、 へstd::stringの呼び出しf()は 2 つの選択肢のいずれかに解決される可能性がf()あり、あいまいです。解決策は、STL がc_str().

于 2008-09-01T06:53:24.820 に答える
14

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

std::stringライブラリでの使用もその 1 つです。

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

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

于 2008-08-28T14:18:08.947 に答える
11

多分それは慰めです:すべてのfstreamは、C ++ 0x標準の作業ドラフトでopen(char const *、...)の隣にopen(string const&、...)を取得しています。(basic_ifstream宣言については、たとえば27.8.1.6を参照してください)

したがって、それが完成して実装されたとき、それはもうあなたを取得しません:)

于 2008-09-15T13:43:44.480 に答える
9

ストリーム IO ライブラリは、STL の前に標準 C++ ライブラリに追加されました。下位互換性を壊さないようにするために、STL が追加されたときに IO ライブラリを変更しないようにすることが決定されました。

于 2008-09-16T15:31:57.223 に答える
3

@バーナード:
モノリス「Unstrung」。「1 人に 1 人、全員に 1 人」は銃士には有効かもしれませんが、クラス デザイナーにはあまり有効ではありません。これは完全に模範的な例ではありませんが、デザインがオーバーデザインに変わったときにどれだけうまくいかないかを示しています。残念ながら、例はあなたの近くの標準ライブラリから取られたものです... ~ http://www.gotw.ca/gotw/084.htm

于 2008-09-15T13:26:24.850 に答える
2

それは取るに足らないことです、それは本当です。std :: stringのインターフェースが大きいとはどういう意味ですか?このコンテキストでは、largeとはどういう意味ですか?多くのメソッド呼び出しですか?私は面白くないです、私は実際に興味があります。

実際に必要な数よりも多くのメソッドがあり、イテレータではなく積分オフセットを使用する動作は少し厄介です(ライブラリの他の部分の動作とは逆です)。

私が思う本当の問題は、C++ライブラリには3つの部分があるということです。古いCライブラリがあり、STLがあり、strings-and-iostreamsがあります。さまざまな部分をブリッジするためにいくつかの努力が払われましたが(たとえば、C ++はオーバーロードをサポートしているため、Cライブラリへのオーバーロードの追加、basic_stringへのイテレーターの追加、iostreamイテレーターアダプターの追加)、詳細を見てください。

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

于 2008-08-28T14:39:40.860 に答える
1

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

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

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

于 2012-11-10T22:36:58.673 に答える
0

これは、依存関係を回避するために考えられ、実行されたと思います。つまり、#include <fstream> は #include <string> を強制するべきではありません。

正直なところ、これは非常に取るに足らない問題のように思えます。より良い質問は、なぜ std::string のインターフェースがそれほど大きいのですか?

于 2008-08-28T14:28:52.883 に答える
0

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

于 2008-08-28T14:14:24.447 に答える