Ответ 1
Эти потоки всегда медленнее, чем функции C-API - довольно распространенное заблуждение, поскольку по умолчанию они синхронизируются с C-слоем. Так что да, это особенность, а не ошибка.
Без ущерба для безопасности типа (и удобочитаемости, в зависимости от вашего вкуса) вы, возможно, получаете производительность с потоками, используя:
std::ios_base::sync_with_stdio (false);
Маленький индикатор:
#include <cstdio>
#include <iostream>
template <typename Test>
void test (Test t)
{
const clock_t begin = clock();
t();
const clock_t end = clock();
std::cout << (end-begin)/double(CLOCKS_PER_SEC) << " sec\n";
}
void std_io() {
std::string line;
unsigned dependency_var = 0;
while (!feof (stdin)) {
int c;
line.clear();
while (EOF != (c = fgetc(stdin)) && c!='\n')
line.push_back (c);
dependency_var += line.size();
}
std::cout << dependency_var << '\n';
}
void synced() {
std::ios_base::sync_with_stdio (true);
std::string line;
unsigned dependency_var = 0;
while (getline (std::cin, line)) {
dependency_var += line.size();
}
std::cout << dependency_var << '\n';
}
void unsynced() {
std::ios_base::sync_with_stdio (false);
std::string line;
unsigned dependency_var = 0;
while (getline (std::cin, line)) {
dependency_var += line.size();
}
std::cout << dependency_var << '\n';
}
void usage() { std::cout << "one of (synced|unsynced|stdio), pls\n"; }
int main (int argc, char *argv[]) {
if (argc < 2) { usage(); return 1; }
if (std::string(argv[1]) == "synced") test (synced);
else if (std::string(argv[1]) == "unsynced") test (unsynced);
else if (std::string(argv[1]) == "stdio") test (std_io);
else { usage(); return 1; }
return 0;
}
С g++ -O3 и большим текстовым файлом:
cat testfile | ./a.out stdio
...
0.34 sec
cat testfile | ./a.out synced
...
1.31 sec
cat testfile | ./a.out unsynced
...
0.08 sec
Как это относится к вашему делу. Измените эту игрушку-тест, добавьте больше тестов и сравните, например. что-то вроде std::cin >> a >> b >> c
с scanf ("%d %d %d", &a, &b, &c);
. Я гарантирую, что с оптимизацией (т.е. Не находясь в режиме отладки) различия в производительности будут незначительными.
Если это не насыщает ваши потребности, вы можете попробовать другие подходы, например. сначала считывая весь файл (может или не может принести больше производительности) или карты памяти (что является не переносным решением, но у них большие рабочие столы).
Update
Отформатированный вход: scanf vs. streams
#include <cstdio>
#include <iostream>
template <typename Test>
void test (Test t)
{
const clock_t begin = clock();
t();
const clock_t end = clock();
std::cout << (end-begin)/double(CLOCKS_PER_SEC) << " sec\n";
}
void scanf_() {
char x,y,c;
unsigned dependency_var = 0;
while (!feof (stdin)) {
scanf ("%c%c%c", &x, &y, &c);
dependency_var += x + y + c;
}
std::cout << dependency_var << '\n';
}
void unsynced() {
std::ios_base::sync_with_stdio (false);
char x,y,c;
unsigned dependency_var = 0;
while (std::cin) {
std::cin >> x >> y >> c;
dependency_var += x + y + c;
}
std::cout << dependency_var << '\n';
}
void usage() { std::cout << "one of (scanf|unsynced), pls\n"; }
int main (int argc, char *argv[]) {
if (argc < 2) { usage(); return 1; }
if (std::string(argv[1]) == "scanf") test (scanf_);
else if (std::string(argv[1]) == "unsynced") test (unsynced);
else { usage(); return 1; }
return 0;
}
Результаты:
scanf: 0.63 sec
unsynced stream: 0.41