直接の答えはそうです、それは大丈夫です。
多くの人がスピードを上げる方法についてさまざまなアイデアを投げかけていますが、どれが最も効果的かについてはかなりの意見の相違があるようです。私は、どの手法が何を実行したかについて少なくともいくつかのアイデアを得るために、簡単なテストプログラムを作成することにしました。
#include <iostream>
#include <string>
#include <sstream>
#include <time.h>
#include <iomanip>
#include <algorithm>
#include <iterator>
#include <stdio.h>
char fmt[] = "%s\n";
static const int count = 3000000;
static char const *const string = "This is a string.";
static std::string s = std::string(string) + "\n";
void show_time(void (*f)(), char const *caption) {
clock_t start = clock();
f();
clock_t ticks = clock()-start;
std::cerr << std::setw(30) << caption
<< ": "
<< (double)ticks/CLOCKS_PER_SEC << "\n";
}
void use_printf() {
for (int i=0; i<count; i++)
printf(fmt, string);
}
void use_puts() {
for (int i=0; i<count; i++)
puts(string);
}
void use_cout() {
for (int i=0; i<count; i++)
std::cout << string << "\n";
}
void use_cout_unsync() {
std::cout.sync_with_stdio(false);
for (int i=0; i<count; i++)
std::cout << string << "\n";
std::cout.sync_with_stdio(true);
}
void use_stringstream() {
std::stringstream temp;
for (int i=0; i<count; i++)
temp << string << "\n";
std::cout << temp.str();
}
void use_endl() {
for (int i=0; i<count; i++)
std::cout << string << std::endl;
}
void use_fill_n() {
std::fill_n(std::ostream_iterator<char const *>(std::cout, "\n"), count, string);
}
void use_write() {
for (int i = 0; i < count; i++)
std::cout.write(s.data(), s.size());
}
int main() {
show_time(use_printf, "Time using printf");
show_time(use_puts, "Time using puts");
show_time(use_cout, "Time using cout (synced)");
show_time(use_cout_unsync, "Time using cout (un-synced)");
show_time(use_stringstream, "Time using stringstream");
show_time(use_endl, "Time using endl");
show_time(use_fill_n, "Time using fill_n");
show_time(use_write, "Time using write");
return 0;
}
VC ++ 2013(x86バージョンとx64バージョンの両方)でコンパイルした後、これをWindowsで実行しました。1回の実行からの出力(出力はディスクファイルにリダイレクトされます)は次のようになります。
Time using printf: 0.953
Time using puts: 0.567
Time using cout (synced): 0.736
Time using cout (un-synced): 0.714
Time using stringstream: 0.725
Time using endl: 20.097
Time using fill_n: 0.749
Time using write: 0.499
予想通り、結果はさまざまですが、興味深い点がいくつかあります。
- NULデバイスに書き込む場合、printf/putsはcoutよりもはるかに高速です
- しかし、実際のファイルに書き込むとき、coutは非常にうまく追いつきます
- かなりの数の提案された最適化はほとんど達成しません
- 私のテストでは、fill_nは他の何よりも高速です
- 圧倒的に最大の最適化はendlを回避することです
- cout.writeが最速の時間を与えました(おそらく大幅な差はありませんが)
最近、コードを編集して、を強制的に呼び出しましたprintf
。Anders Kaseorgは親切にも指摘してくれました。これはg++
、特定のシーケンスprintf("%s\n", foo);
がと同等であることを認識しputs(foo);
、それに応じてコードを生成します(つまり、puts
の代わりに呼び出すコードを生成しますprintf
)。フォーマット文字列をグローバル配列に移動し、それをフォーマット文字列として渡すと、同じ出力が生成されますが、printf
の代わりに経由で生成されputs
ます。もちろん、いつか最適化される可能性もありますが、少なくとも今のところ(g ++ 5.1)のテストでは、g++ -O3 -S
実際に呼び出していることを確認してprintf
います(前のコードが呼び出しにコンパイルされていますputs
)。