如何通过Unix read系统调用直接读取数据到std::vector?
解决方案
首先得纠正你代码里的一个问题:调用reserve(n)后,vector的size还是0,这时候直接用&buf[0]访问元素属于未定义行为——因为vector里根本没有元素存在。正确的做法是用buf.data()获取指向预留内存的指针,它在reserve后是有效的(只要你写入的字节数不超过reserve的容量)。
接下来解决size更新的问题:你担心resize()会覆盖数据,但对于uint8_t这种**平凡类型(trivial type)**来说,resize(r)并不会覆盖已写入的内容。原因是:平凡类型的默认构造函数是空操作,当你调用resize(r)且r <= capacity时,vector只会修改内部的size计数,不会对内存做任何初始化或覆盖操作——之前用read()写入的数据会完整保留。
正确的示例代码如下:
#include <vector> #include <cstdint> #include <unistd.h> // 包含read()的声明 // 假设fd是已打开的文件描述符,n是想要读取的最大字节数 std::vector<uint8_t> buf; buf.reserve(n); // 预留足够的内存空间,避免后续扩容 ssize_t r = read(fd, buf.data(), n); if (r == -1) { // 处理读取错误,比如perror("read failed") } else if (r == 0) { // 到达文件末尾,将vector size设为0 buf.resize(0); } else { // 调整vector的size到实际读取的字节数 buf.resize(static_cast<size_t>(r)); }
如果你对resize()的行为仍有顾虑,还有一种可选方案(虽没必要但更严谨):先将vector的size设为0,reserve后写入,再通过insert添加元素——不过这种方法会产生额外的内存拷贝,效率不如直接resize:
std::vector<uint8_t> buf; buf.reserve(n); ssize_t r = read(fd, buf.data(), n); if (r > 0) { buf.insert(buf.end(), reinterpret_cast<uint8_t*>(buf.data()), reinterpret_cast<uint8_t*>(buf.data()) + r); // 注意:insert后reserve的容量会被保留,但这里做了一次不必要的拷贝 }
显然第一种方案更高效,也是实际项目中常用的写法。
内容的提问来源于stack exchange,提问作者Steve Summit
相关产品推荐
相关产品推荐

