与字符数组相比,使用矢量<char>作为输入缓冲区有什么优势?

What is the advantage of using vector<char> as input buffer over char array?

本文关键字:gt 输入 缓冲区 什么 char lt 数组 字符      更新时间:2023-10-16

我正在进行网络编程,我见过有人使用vector作为套接字的输入缓冲区,而不是char数组。

我想知道这样做有什么好处。

提前谢谢。。

vector<char>本质上只是一个托管字符数组。

所以你可以写:

{
    vector<char> buf(4096);
    ...
    int result = recv(fd, &buf[received_so_far], buf.size() - received_so_far);
    ...
}

向量"知道"它的大小,所以您可以在任何地方使用buf.size(),而不必担心超出缓冲区。您还可以更改声明中的大小,并使其在任何地方生效,而不需要任何混乱的#定义。

buf的这种使用将在堆上分配底层数组,并且当buf超出范围时,它将自动释放它,无论这种情况如何发生(例如异常或早期返回)。因此,您可以获得堆栈分配的良好语义,同时仍然将大型对象保留在堆上。

您可以非常有效地使用buf.swap()将底层字符数组的所有权"移交"给另一个vector<char>。(这对网络流量来说是个好主意……现代网络速度很快。你最不想做的就是为从网络接收到的每个字节创建另一个副本。)而且你仍然不必担心显式释放内存。

对于这个特定的应用程序,这些都是我脑海中浮现的巨大优势。

使用向量是:

  • 容易长大的记忆空间
  • 易于复制数据
  • 易于释放

我的主要原因:

  • 它的异常安全。
    • 无论出现什么问题,矢量都不会泄漏内存

vector可以很容易地调整大小,并允许方便地部分删除数据,这是一大优势。在许多情况下,使用固定大小的数组是不方便的——例如,您将读取数据块,并以比接收到的块更小的块处理接收到的数据。然后,您想知道实际剩余的数据量,即vector.size(),您不必将其存储在单独的变量中,当您删除部分数据时,vector将为您移动剩余的数据。

如果您曾经用Java编程过网络应用程序,那么您可能熟悉ByteBuffer和IoBuffer。这两个类通过非常简单直观的界面使缓冲区处理变得非常容易。

在C++的世界里,非常幸运的是,有了标准向量类,这两个类提供的一切都可以使用。由于vector可以动态增长,它甚至比ByteBuffer和IoBuffer更强大。只需编写代码,您就会在字节缓冲区包装器中找到所需的一切。

一些明显的优势:

  • 使用向量预分配内存::reserve
  • 使用矢量记住缓冲区位置::size
  • 使用矢量增大/清除缓冲区::调整大小
  • 使用&您的向量[0]
  • 使用vector::swap传输缓冲区所有权
  • 。。。还有更多有待发现

std::vector<char> buffer(SIZE)std::array<char, SIZE> buffer之间的一个主要区别是SIZE参数的位置:对于vector,您只需要在运行时知道大小,如果需要,甚至可以更改大小。对于arraySIZE是一个模板参数,因此您需要在编译时就已经知道它,并且在重新编译之前它一直是固定的。因此,基本上std::array只是C风格数组char buffer[SIZE]的包装器。虽然由于C++14标准,C风格的数组可以在C++中动态调整大小,但std::array总是静态调整大小。但是,请注意,C风格的数组通常在堆栈上分配,并且在大多数实现中堆栈空间是有限的。

下一个区别是,std::vector对其元素执行值初始化,这通常意味着将它们设置为零(除非您用自定义构造函数覆盖它),而std::array和C风格的数组则保持其内容未初始化。

因此:

  • 如果您需要一个已知固定大小的缓冲区,如果该大小不超过几千字节,并且该缓冲区的内容将由应用程序正确写入,请使用std::array或C样式数组。这是更快的解决方案
  • 否则,请使用std::vector。这是更安全的解决方案