代码之家  ›  专栏  ›  技术社区  ›  kal

为什么snprintf比ostringstream快?

  •  27
  • kal  · 技术社区  · 16 年前

    我在某个地方读到snprintf比ostringstream快。有人有过这样的经历吗?如果是,为什么它更快。

    9 回复  |  直到 16 年前
        1
  •  27
  •   Max Lybbert    13 年前

    std::ostringstream 不是 需要 速度较慢,但实施时通常较慢。 FastFormat's website has some benchmarks .

    流的标准库设计支持的远不止 snprintf 做。该设计旨在可扩展,包括 protected virtual 由公开方法调用的方法。这允许您从其中一个流类派生,并保证如果您过载 protect ed方法,你会得到你想要的行为。我相信编译器可以避免 虚拟 函数调用,但我不知道有任何编译器会这样做。

    此外,流操作通常在内部使用可增长缓冲区;这意味着相对较慢的内存分配。

        2
  •  9
  •   user52875    16 年前

    我们用sprintf(使用静态分配的缓冲区)替换了内部循环中的一些字符串流,这在msvc和gcc中都有很大的不同。我想这段代码的动态内存管理:

    {
      char buf[100];
      int i = 100;
      sprintf(buf, "%d", i);
      // do something with buf
    }
    

    {
      std::stringstream ss;
      int i = 100;
      ss << i;
      std::string s = ss.str();
      // do something with s
    }
    

    但我对stringstreams的整体表现非常满意。

        3
  •  8
  •   Johannes Schaub - litb    16 年前

    有些人可能会告诉你,这些函数不能比彼此更快,但它们的实现可以。没错,我想我会同意的。

    除了基准测试之外,你不太可能注意到其他方面的差异。c++流媒体的原因 倾向 速度较慢是因为它们更灵活。灵活性往往以时间或代码增长为代价。

    在这种情况下,C++流基于流缓冲区。就其本身而言,流只是保持格式和错误标志的外壳,并调用正确的 i/o c++标准库的方面(例如,numput打印数字),将格式良好的值打印到连接到c++流的底层流缓冲区中。

    所有这些机制——方面和缓冲区——都是通过虚拟函数实现的。虽然确实没有标记 注意,这些函数的实现速度必须比c stdio悬架慢 这一事实将使它们比正常使用c stdio函数慢一些(我不久前用gcc/libstdc++进行了基准测试,事实上注意到了速度的减慢,但在日常使用中几乎没有注意到)。

        4
  •  3
  •   Paul Beckingham    16 年前

    这绝对是具体的实施。

    但如果你真的想知道,写两个小程序,并对它们进行比较。您需要包括您所想到的典型用法,这两个程序需要生成相同的字符串,并且您将使用分析器来查看计时信息。

    那你就知道了。

        5
  •  1
  •   Johann Gerell    16 年前

    一个问题可能是 ostringstream 带来额外的开销。不过,我还没有做任何测量。

        6
  •  0
  •   Community CDub    8 年前

    litb said ,标准流支持许多我们并不总是需要的东西。 一些流实现摆脱了这种从未使用过的灵活性,请参阅 FAStream 例如。

        7
  •  0
  •   George Stocker NotMe    16 年前

    这很可能是因为 sprintf 是以汇编形式编写的CRT的一部分。这个 ostringstream 是STL的一部分,可能写得更通用一些,需要处理OOP代码/开销。

        8
  •  0
  •   Matthew    15 年前

    是的,如果你用Visual C++5.0在几百万个数字上运行下面的函数,第一个版本大约需要第二个版本的两倍时间,并产生相同的输出。

    将紧密循环编译为.exe并运行Windows timethis something.exe' or the Linux “时间”是我调查自己大部分表演好奇心的方式。(“timethis”可以在网上的某个地方找到)

    void Hex32Bit(unsigned int n, string &result)
    {
    #if 0
        stringstream ss;
        ss
            << hex
            << setfill('0')
            << "0x" << setw(8) << n
        ;
        result = ss.str();
    #else
        const size_t len = 11;
        char temp[len];
        _snprintf(temp, len, "0x%08x", n);
        temp[len - 1] = '\0';
        result = temp;
    #endif
    }
    
        9
  •  -1
  •   sykora    16 年前

    我知道printf家族函数比相应的C++函数(cout、cin和其他流)更快的一个原因是后者进行类型检查。由于这通常涉及对超载操作员的一些请求,因此可能需要一些时间。

    事实上,在编程竞赛中,通常建议您使用printf等人,而不是cout/cin,正是出于这个原因。