'printf' по сравнению с 'cout' в C++

Между чем различие printf() и cout в C++?

343
задан Deduplicator 7 June 2018 в 03:54
поделиться

7 ответов

Люди часто утверждают, что 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);
    }
}
41
ответ дан 23 November 2019 в 00:33
поделиться
cout<< "Hello";
printf("%s", "Hello"); 

Оба используются для печати значений. У них совершенно другой синтаксис. В C ++ есть и то, и другое, C есть только printf.

-1
ответ дан 23 November 2019 в 00:33
поделиться

Одна из них - это функция, которая выводит на стандартный вывод. Другой - объект, который предоставляет несколько функций-членов и перегрузок operator << , которые выводятся на стандартный вывод. Есть еще много различий, которые я мог бы перечислить, но я не уверен, что вам нужно.

30
ответ дан 23 November 2019 в 00:33
поделиться

Из 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 /)

198
ответ дан 23 November 2019 в 00:33
поделиться

На мой взгляд, настоящие отличия, которые заставили бы меня использовать 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 проще.

12
ответ дан 23 November 2019 в 00:33
поделиться

С примитивами, вероятно, совершенно не имеет значения, какой из них вы используете. Я говорю, что он полезен, когда вы хотите выводить сложные объекты.

Например, если у вас есть класс,

#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 в новом приложении, вам действительно не о чем беспокоиться. о выходе.

4
ответ дан 23 November 2019 в 00:33
поделиться

И я цитирую :

В терминах высокого уровня основными отличиями являются безопасность типов (cstdio его нет), производительность (большинство реализаций iostreams медленнее, чем cstdio) и расширяемость (iostreams позволяет настраиваемые целевые объекты вывода и непрерывный вывод определяемых пользователем типов).

38
ответ дан 23 November 2019 в 00:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: