質問
C ++ファイルI / Oは、CファイルI / Oよりも厳しいです。
C ++では、ファイルI / O用の新しいライブラリを作成するのは便利ですか?つまり、<fstream>
誰でもC ++ファイルI / Oに利点があることを教えてもらえますか?
解決
意見
C ++ストリームを使用する実際のプロジェクトは知りません。それらは遅すぎて使用が困難です。 FastFormat や Boost は、最新のACCU Overloadマガジンにそれらについての記事があると主張しています。個人的には、C ++で過去15年ほどc FILEライブラリを使用しており、変更する理由はまだありません。
速度
基本的な速度の問題を示すための小さなテストプログラム(すぐにノックします):
#include <stdio.h>
#include <time.h>
#include<iostream>
#include<fstream>
using namespace std;
int main( int argc, const char* argv[] )
{
const int max = 1000000;
const char* teststr = "example";
int start = time(0);
FILE* file = fopen( "example1", "w" );
for( int i = 0; i < max; i++ )
{
fprintf( file, "%s:%d\n", teststr, i );
}
fclose( file );
int end = time(0);
printf( "C FILE: %ds\n", end-start );
start = time(0);
ofstream outdata;
outdata.open("example2.dat");
for( int i = 0; i < max; i++ )
{
outdata << teststr << ":" << i << endl;
}
outdata.close();
end = time(0);
printf( "C++ Streams: %ds\n", end-start );
return 0;
}
そして私のPCでの結果:
C FILE: 5s
C++ Streams: 260s
Process returned 0 (0x0) execution time : 265.282 s
Press any key to continue.
ご覧のとおり、この単純な例は52倍遅いです。より速くする方法があることを願っています!
注:この例でendlを「\ n」に変更すると、C ++ストリームがFILE *ストリームよりも3倍だけ遅くなりました( jalf )より高速にする方法があるかもしれません。
使いにくい
printf()は簡潔ではないとは言えませんが、マクロコードの初期WTFを超えると、より柔軟(IMO)で理解しやすくなります。
double pi = 3.14285714;
cout << "pi = " << setprecision(5) << pi << '\n';
printf( "%.5f\n", pi );
cout << "pi = " << fixed << showpos << setprecision(3) << pi << '\n';
printf( "%+.3f\n", pi );
cout << "pi = " << scientific << noshowpos << pi<< '\n';
printf( "%e\n", pi );
質問
はい、より良いC ++ライブラリが必要かもしれません。多くは FastFormat がそのライブラリであり、時間だけがわかります。
dave
他のヒント
バッファオーバーランの解消は、C ++にとって大きな勝利のように思えます。
ご覧ください
http://www.ddj.com/cpp/184403651
その場合、C I / OよりもC ++ I / Oを好むでしょう。
短いCでは、読み取りまたは書き込み前のデータサイズと速度を知っている場合に適しています。 データサイズがわからない場合や効率的なコードを作成する場合は、C ++をお勧めします。
David Allan Finchの回答に応じて、ベンチマークコードのエラーを修正し(1行ごとにC ++バージョンのストリームをフラッシュしました)、テストを再実行しました。
C ++ループは次のようになります。
start = time(0);
{
ofstream outdata("example2.txt");
for( int i = 0; i < max; i++ )
{
outdata << teststr << ":" << i << "\n"; // note, \n instead of endl
}
}
end = time(0);
10000000回の反復を実行します(元のコードの10倍です。そうしないと、数値が小さすぎてtime()の手に負えない解像度で意味のあるものが得られません) 出力は次のとおりです。
G++ 4.1.2:
C FILE: 4s
C++ Streams: 6s
MSVC9.0:
C FILE: 10s
C++ Streams: 23s
(注、MSVCバージョンはラップトップで実行し、ハードドライブが大幅に遅い)
ただし、これにより、実装に応じて1.5〜2.3倍のパフォーマンスの違いが生じます。およびその他の外部要因。
printf()/ fwriteスタイルのI / OとC ++ IOストリームのフォーマットのパフォーマンスの違いは、実装に大きく依存します。一部の実装(たとえば、ビジュアルC ++)は、FILE *オブジェクトの上にIOストリームを構築します。これにより、実装の実行時の複雑さが増す傾向があります。ただし、この方法でライブラリを実装するための特定の制約はないことに注意してください。
私自身の意見では、C ++ I / Oの利点は次のとおりです。
- 前述のタイプセーフティ。
- 実装の柔軟性。コードを記述して、汎用ostreamまたはistreamオブジェクトとの間で特定のフォーマットまたは入力を行うことができます。アプリケーションは、任意の種類の派生ストリームオブジェクトでこのコードを呼び出すことができます。ファイルに対して記述してテストしたコードをソケット、シリアルポート、またはその他の種類の内部ストリームに適用する必要がある場合、その種類のI / Oに固有のストリーム実装を作成できます。この方法でCスタイルのI / Oを拡張することは、ほとんど不可能です。
- ロケール設定の柔軟性:単一のグローバルロケールを使用するCのアプローチには、重大な欠陥があります。私は、コードの下のグローバルロケール設定を変更し、出力を完全に台無しにするライブラリコード(DLL)を呼び出した場合を経験しました。 C ++ストリームを使用すると、任意のロケールをストリームオブジェクトにimbue()できます。
std :: ifstreamおよびstd :: ofstreamはすでにstlライブラリにあります。独自に作成する必要はありません。
主な利点は、すべての出力と入力がタイプセーフであることです。
CとC ++は2つの異なる言語です。 C ++ file ioは慣れるまで時間がかかりますが、アルゴリズムや例外などを使用すると、自然に配置される傾向があります。
C ++のファイルで入力/出力を行う必要があるときはいつでも、2行だけを使用します。
freopen("input.txt","r",stdin); // for input from file
freopen("output.txt","w",stdout);// for output from file
コンソールから通常行うように変数をスキャンできるようになり、出力として印刷するものはすべてoutput.txtファイルに表示されます。
したがって、c ++でのファイルI / Oは難しいとは思いません。cよりも簡単です。
たくさん。欠点も。詳細については、C ++言語のFAQを参照してください。要するに、型安全性とユーザー定義型。