如何让cout输出更快?

6
有没有什么办法可以让这个程序运行得更快,但仍然能够完成相同的任务?
#include <iostream>

int box[80][20];

void drawbox()
{
    for(int y = 0; y < 20; y++)
    {
        for(int x = 0; x < 80; x++)
        {
            std::cout << char(box[x][y]);
        }
    }
}

int main(int argc, char* argv[])
{
    drawbox();
    return(0);
}

IDE: DEV C++ || OS: Windows


9
最好先构建字符串并在一次输出,或者在每个外部循环中输出一次,这将是1或20个cout,而不是20*80=1600个。 - Marc B
4
一个缓冲I/O库本应该为你处理这个问题。不幸的是,C++ iostreams 在缓冲和 I/O 方面都非常慢。如果你想看一些漂亮的基准测试,可以看看我提出的问题。 - Ben Voigt
1
@Marc B:为什么不把那变成一个真正的答案呢? - Drew Hall
1
缓冲有助于实际的I/O操作,但函数调用通常是_不_免费的。二十个每个八十个字符的输出几乎肯定比每个一个字符的一千六百个更快。这并不是因为它实际上将这些字符发送到一个_设备_,而是因为它正在构建和拆除堆栈帧,以及其他一些事情。 - paxdiablo
1
@Drew: 因为我只是瞎猜的,我从未写过C++程序的第一行。 - Marc B
显示剩余2条评论
3个回答

4

正如Marc B在评论中所说,首先将输出放入字符串中应该更快:

int box[80][20];

void drawbox()
{
    std::string str = "";
    str.reserve(80 * 20);

    for(int y = 0; y < 20; y++)
    {
        for(int x = 0; x < 80; x++)
        {
            str += char(box[x][y]);
        }
    }

    std::cout << str << std::flush;
}

13
记得预分配那个字符串空间。std::string并没有像std::vector那样针对优化分配模式。 - Ben Voigt
@Ben Voigt:如果这是必要的,我会非常失望...这绝对听起来像是实现质量问题... - Matthieu M.
2
@ Matthieu M:我怀疑任何默认的字符串实现都不会预留1600个字节。因此,在完成写入之前可能会有多次重新分配内存。预先保留所需空间是一个好主意。 - Martin York

2
显而易见的解决方案是以不同的方式声明box数组:
char box[20][81];

接下来,您可以一次输出一行。如果由于某种原因无法执行此操作,则无需在此处使用 std::string -- 使用 char 数组速度更快:

char row[81] ; row[80] = 0 ;
for (int y = 0; y < 20; y++)
  {
  for (int x = 0 ; x < 80 ; x++)
    row[x] = char(box[x][y]) ;
  std::cout << row ;
  // Don't you want a newline here?
  }

这正是我所想的。没有必要动态分配一个每次大小都相同的数组。 - GManNickG

1
当然,使用来自 stdio.hputchar

@Mark:真的吗?你确定瓶颈不是控制台窗口而不是你的程序吗?你能检查一下,如果输出重定向到文件时速度是否更快吗? - Ben Voigt
这里的问题不在于使用C++还是C。(实际上,在他的例子中,应该使用cstdio库中的putchar()函数。)问题在于为每个字符打印数据。 - BjoernD
1
@Bjoern:putchar是有缓存的,与实际在屏幕上绘制文本相比应该会更快。 - Ben Voigt
2
C++ 的输入输出函数也是带缓冲区的。 - Ed S.
@Ed:是的,但它们需要一个函数调用(不是内联的,因为它们是虚拟的),除非你有一个非常聪明的链接器并且启用了LTO(即使这样,它也可能无法工作)。我不知道putchar是否是内联的。 - Matthieu M.
@Matthieu M.:只有streambufoverflow()是虚函数。对于op<<(一个自由函数)的std::ostream/char版本的大多数调用不应涉及虚函数调用。 - CB Bailey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接