printf()和cout在c++中的区别是什么?


当前回答

当然,你可以把“something”写得更好一点,以保持维护:

#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&);

        void print() const { printf("%i, %i, %i\n", a, b, c); }
};

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
    s.print(); // Simple as well, isn't it?

    // Output with cout
    cout << s << endl;

    return 0;
}

还有一个cout vs. printf的扩展测试,如果有人想做更多的测试,添加了一个'double'的测试(Visual Studio 2008,可执行文件的发布版本):

#include <stdio.h>
#include <iostream>
#include <ctime>

class TimedSection {
    char const *d_name;
    //timespec d_start;
    clock_t d_start;

    public:
        TimedSection(char const *name) :
            d_name(name)
        {
            //clock_gettime(CLOCK_REALTIME, &d_start);
            d_start = clock();
        }
        ~TimedSection() {
            clock_t end;
            //clock_gettime(CLOCK_REALTIME, &end);
            end = clock();
            double duration = /*1e3 * (end.tv_sec - d_start.tv_sec) +
                              1e-6 * (end.tv_nsec - d_start.tv_nsec);
                              */
                              (double) (end - d_start) / CLOCKS_PER_SEC;

            std::cerr << d_name << '\t' << std::fixed << duration * 1000.0 << " ms\n";
        }
};


int main() {
    const int iters = 1000000;
    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);
    }
    {
        TimedSection s("cout with formatted double (width & precision once)");
        std::cout << std::fixed << std::scientific << std::right << std::showpoint;
        std::cout.width(8);
        for (int i = 0; i < iters; ++i)
            std::cout << text << 8.315 << i << '\n';
    }
    {
        TimedSection s("cout with formatted double (width & precision on each call)");
        std::cout << std::fixed << std::scientific << std::right << std::showpoint;

        for (int i = 0; i < iters; ++i)
            { std::cout.width(8);
              std::cout.precision(3);
              std::cout << text << 8.315 << i << '\n';
            }
    }
    {
        TimedSection s("printf with formatted double");
        for (int i = 0; i < iters; ++i)
            printf("%8.3f%i\n", 8.315, i);
    }
}

结果是:

cout with only endl    6453.000000 ms
cout with only '\n'    125.000000 ms
printf with only '\n'    156.000000 ms
cout with string constant and endl    6937.000000 ms
cout with string constant and '\n'    1391.000000 ms
printf with string constant and '\n'    3391.000000 ms
cout with some stuff and endl    9672.000000 ms
cout with some stuff and '\n'    7296.000000 ms
printf with some stuff and '\n'    12235.000000 ms
cout with formatted double (width & precision once)    7906.000000 ms
cout with formatted double (width & precision on each call)    9141.000000 ms
printf with formatted double    3312.000000 ms

其他回答

当然,你可以把“something”写得更好一点,以保持维护:

#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&);

        void print() const { printf("%i, %i, %i\n", a, b, c); }
};

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
    s.print(); // Simple as well, isn't it?

    // Output with cout
    cout << s << endl;

    return 0;
}

还有一个cout vs. printf的扩展测试,如果有人想做更多的测试,添加了一个'double'的测试(Visual Studio 2008,可执行文件的发布版本):

#include <stdio.h>
#include <iostream>
#include <ctime>

class TimedSection {
    char const *d_name;
    //timespec d_start;
    clock_t d_start;

    public:
        TimedSection(char const *name) :
            d_name(name)
        {
            //clock_gettime(CLOCK_REALTIME, &d_start);
            d_start = clock();
        }
        ~TimedSection() {
            clock_t end;
            //clock_gettime(CLOCK_REALTIME, &end);
            end = clock();
            double duration = /*1e3 * (end.tv_sec - d_start.tv_sec) +
                              1e-6 * (end.tv_nsec - d_start.tv_nsec);
                              */
                              (double) (end - d_start) / CLOCKS_PER_SEC;

            std::cerr << d_name << '\t' << std::fixed << duration * 1000.0 << " ms\n";
        }
};


int main() {
    const int iters = 1000000;
    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);
    }
    {
        TimedSection s("cout with formatted double (width & precision once)");
        std::cout << std::fixed << std::scientific << std::right << std::showpoint;
        std::cout.width(8);
        for (int i = 0; i < iters; ++i)
            std::cout << text << 8.315 << i << '\n';
    }
    {
        TimedSection s("cout with formatted double (width & precision on each call)");
        std::cout << std::fixed << std::scientific << std::right << std::showpoint;

        for (int i = 0; i < iters; ++i)
            { std::cout.width(8);
              std::cout.precision(3);
              std::cout << text << 8.315 << i << '\n';
            }
    }
    {
        TimedSection s("printf with formatted double");
        for (int i = 0; i < iters; ++i)
            printf("%8.3f%i\n", 8.315, i);
    }
}

结果是:

cout with only endl    6453.000000 ms
cout with only '\n'    125.000000 ms
printf with only '\n'    156.000000 ms
cout with string constant and endl    6937.000000 ms
cout with string constant and '\n'    1391.000000 ms
printf with string constant and '\n'    3391.000000 ms
cout with some stuff and endl    9672.000000 ms
cout with some stuff and '\n'    7296.000000 ms
printf with some stuff and '\n'    12235.000000 ms
cout with formatted double (width & precision once)    7906.000000 ms
cout with formatted double (width & precision on each call)    9141.000000 ms
printf with formatted double    3312.000000 ms

我引用一下:

在高层术语中,主要的区别是类型安全(cstdio 没有它),性能(大多数iostreams实现都有 比cstdio慢)和可扩展性(iostreams允许 自定义输出目标和用户定义类型的无缝输出)。

这里没有提到的两点我认为很重要:

1)如果你还没有使用STL, cout会携带很多包袱。它向目标文件中添加的代码是printf的两倍多。对于字符串也是如此,这也是我倾向于使用自己的字符串库的主要原因。

2) cout使用重载的<<操作符,我觉得这很不幸。如果还将<<运算符用于其预期目的(左移),则会增加混淆。我个人不喜欢为了与其预期用途无关的目的而重载操作符。

底线:如果我已经在使用STL,我将使用cout(和字符串)。否则,我倾向于避免它。

一个是输出到标准输出的函数。另一个是一个对象,它提供了几个成员函数和输出到stdout的操作符<<的重载。我可以列举更多的不同之处,但我不确定你想要的是什么。

对于原语,使用哪个原语可能并不重要。当你想输出复杂的对象时它才有用。

例如,如果你有一门课,

#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”,您实际上不必担心输出。