Люди часто утверждают, что printf
намного быстрее. Во многом это миф. Я только что протестировал его и получил следующие результаты:
cout with only endl 1461.310252 ms
cout with only '\n' 343.080217 ms
printf with only '\n' 90.295948 ms
cout with string constant and endl 1892.975381 ms
cout with string constant and '\n' 416.123446 ms
printf with string constant and '\n' 472.073070 ms
cout with some stuff and endl 3496.489748 ms
cout with some stuff and '\n' 2638.272046 ms
printf with some stuff and '\n' 2520.318314 ms
Заключение: если вам нужны только символы новой строки, используйте printf
; в противном случае cout
работает почти так же или даже быстрее. Более подробную информацию можно найти в моем блоге .
Для ясности, я не пытаюсь сказать, что iostream
всегда лучше, чем printf
; Я просто пытаюсь сказать, что вы должны принимать обоснованное решение, основываясь на реальных данных, а не на безумных предположениях, основанных на каком-то распространенном, вводящем в заблуждение предположении.
Обновление: вот полный код, который я использовал для тестирования. Скомпилировано с помощью g ++
без каких-либо дополнительных параметров (кроме -lrt
для определения времени).
#include <stdio.h>
#include <iostream>
#include <ctime>
class TimedSection {
char const *d_name;
timespec d_start;
public:
TimedSection(char const *name) :
d_name(name)
{
clock_gettime(CLOCK_REALTIME, &d_start);
}
~TimedSection() {
timespec end;
clock_gettime(CLOCK_REALTIME, &end);
double duration = 1e3 * (end.tv_sec - d_start.tv_sec) +
1e-6 * (end.tv_nsec - d_start.tv_nsec);
std::cerr << d_name << '\t' << std::fixed << duration << " ms\n";
}
};
int main() {
const int iters = 10000000;
char const *text = "01234567890123456789";
{
TimedSection s("cout with only endl");
for (int i = 0; i < iters; ++i)
std::cout << std::endl;
}
{
TimedSection s("cout with only '\\n'");
for (int i = 0; i < iters; ++i)
std::cout << '\n';
}
{
TimedSection s("printf with only '\\n'");
for (int i = 0; i < iters; ++i)
printf("\n");
}
{
TimedSection s("cout with string constant and endl");
for (int i = 0; i < iters; ++i)
std::cout << "01234567890123456789" << std::endl;
}
{
TimedSection s("cout with string constant and '\\n'");
for (int i = 0; i < iters; ++i)
std::cout << "01234567890123456789\n";
}
{
TimedSection s("printf with string constant and '\\n'");
for (int i = 0; i < iters; ++i)
printf("01234567890123456789\n");
}
{
TimedSection s("cout with some stuff and endl");
for (int i = 0; i < iters; ++i)
std::cout << text << "01234567890123456789" << i << std::endl;
}
{
TimedSection s("cout with some stuff and '\\n'");
for (int i = 0; i < iters; ++i)
std::cout << text << "01234567890123456789" << i << '\n';
}
{
TimedSection s("printf with some stuff and '\\n'");
for (int i = 0; i < iters; ++i)
printf("%s01234567890123456789%i\n", text, i);
}
}
cout<< "Hello";
printf("%s", "Hello");
Оба используются для печати значений. У них совершенно другой синтаксис. В C ++ есть и то, и другое, C есть только printf.
Одна из них - это функция, которая выводит на стандартный вывод. Другой - объект, который предоставляет несколько функций-членов и перегрузок operator <<
, которые выводятся на стандартный вывод. Есть еще много различий, которые я мог бы перечислить, но я не уверен, что вам нужно.
Из FAQ по C ++ :
[15.1] Почему я должен использовать
вместо традиционного
?
Повысьте безопасность типов, уменьшите количество ошибок, разрешите расширяемость и обеспечивают наследуемость.
printf ()
, возможно, не сломан, аscanf ()
, возможно, пригоден для жизни, несмотря на то, что он подвержен ошибкам, однако оба ограничены в отношении того, что может делать ввод-вывод C ++. Ввод-вывод C ++ (с использованием<<
и>>
) относительно C (с использованиемprintf ()
иscanf ()
):
- Более безопасный тип: с
тип объекта, вводимого / выводимого, будет статически известно компилятору. В напротив,
использует поля "%" для определять типы динамически.
- Меньше ошибок: с
нет избыточных токены "%", которые должны быть согласованы с фактическими объектами, которые вводятся / выводятся. Удаление избыточности удаляет класс ошибок.
- Расширяемый: механизм C ++
позволяет создавать новые определяемые пользователем типы для ввода-вывода без нарушения существующий код.Представьте себе хаос, если все одновременно добавляли новые несовместимые поля "%" в
printf ()
иscanf ()
?!- Наследование: механизм C ++
построен из реальных классов. например
std :: ostream
иstd :: istream
. В отличие от
ФАЙЛ *
, это реальные классы и следовательно, наследуется. Это означает, что вы можете есть другие определенные пользователем вещи, которые выглядят и действуют как потоки, но делай все, что странно и чудесно вещи, которые вы хотите. Ты автоматически использовать миллионы строк Код ввода-вывода, написанный пользователями, которых вы не знаете даже знать, и им не нужно знать о своем "расширенном потоке" класс.
С другой стороны, printf
значительно быстрее, что может оправдать его использование вместо cout
в очень конкретных и ограниченных случаях. Всегда сначала профиль. (См., Например, http://programming-designs.com/2009/02/c-speed-test-part-2-printf-vs-cout /)
На мой взгляд, настоящие отличия, которые заставили бы меня использовать cout, а не printf, заключаются в следующем:
1) Оператор << может быть перегружен для моих классов.
2) Выходной поток для cout можно легко преобразовать в файл: (: copy paste:)
#include <iostream>
#include <fstream>
using namespace std;
int main ()
{
cout << "This is sent to prompt" << endl;
ofstream file;
file.open ("test.txt");
streambuf* sbuf = cout.rdbuf();
cout.rdbuf(file.rdbuf());
cout << "This is sent to file" << endl;
cout.rdbuf(sbuf);
cout << "This is also sent to prompt" << endl;
return 0;
}
3) Я считаю cout более читабельным, особенно когда у нас много параметров.
Одна проблема с cout
- это параметры форматирования. Форматировать данные (точность, выравнивание и т. Д.) В printf
проще.
С примитивами, вероятно, совершенно не имеет значения, какой из них вы используете. Я говорю, что он полезен, когда вы хотите выводить сложные объекты.
Например, если у вас есть класс,
#include <iostream>
#include <cstdlib>
using namespace std;
class Something
{
public:
Something(int x, int y, int z) : a(x), b(y), c(z) { }
int a;
int b;
int c;
friend ostream& operator<<(ostream&, const Something&);
};
ostream& operator<<(ostream& o, const Something& s)
{
o << s.a << ", " << s.b << ", " << s.c;
return o;
}
int main(void)
{
Something s(3, 2, 1);
// output with printf
printf("%i, %i, %i\n", s.a, s.b, s.c);
// output with cout
cout << s << endl;
return 0;
}
Вышеупомянутое может показаться не таким уж большим, но предположим, что вам нужно вывести это в нескольких местах вашего кода. Мало того, допустим, вы добавили поле «int d». С cout вам нужно изменить его только один раз. Однако с printf вам придется изменить его, возможно, во многих местах, и не только это, вы должны напомнить себе, какие из них выводить.
С учетом вышесказанного, с помощью cout вы можете сократить много времени, затрачиваемого на сопровождение вашего кода, и не только то, что если вы повторно используете объект Something в новом приложении, вам действительно не о чем беспокоиться. о выходе.
И я цитирую :
В терминах высокого уровня основными отличиями являются безопасность типов (cstdio его нет), производительность (большинство реализаций iostreams медленнее, чем cstdio) и расширяемость (iostreams позволяет настраиваемые целевые объекты вывода и непрерывный вывод определяемых пользователем типов).