使用vector<char>作为输入缓冲区
一、引言
当我们编写代码:实现网络接收、读取文件内容等功能时,我们往往要在内存中开辟一个输入缓冲区(又名:input buffer/读缓冲区)来存贮接收到的数据。在C++里面我们可以用如下方法开辟输入缓冲区。
①使用C语言中的数组:
char buf[100] = {0};
②使用malloc/new动态分配内存:
char *pBuf = new char[100];
③使用std::string
string sBuf;
④使用vector<char> / vector<unsigned char>
vector<char> vecBuf(100);
在这里面推荐使用方法④作为输入缓冲区。方法①在栈中开辟空间,对于大数组可能会有栈内存不够的问题。方法②在堆上分配内存,但是使用完需要程序员自行手动释放(delete pBuf),而且需要一个额外的变量记录申请空间的大小。方法③只能处理字符串,不能处理二进制数据。下面具体阐述使用vector<char>作为输入缓冲区的优势。
二、使用vector<char>作为输入缓冲区的优势
(一)跟方法①相比,vector<char>可以在程序运行时调整大小
例子1:
main.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <windows.h>// 通过stat结构体 获得文件大小,单位字节
size_t getFileSize1(const char* fileName) {if (fileName == NULL) {return 0;}// 这是一个存储文件(夹)信息的结构体,其中有文件大小和创建时间、访问时间、修改时间等struct stat statbuf;// 提供文件名字符串,获得文件属性结构体stat(fileName, &statbuf);// 获取文件大小size_t filesize = statbuf.st_size;return filesize;
}int main()
{const char *fileName = "test.txt";std::ifstream ifs(fileName);int nFileSize = getFileSize1(fileName);char buf[100] = { 0 };ifs.read(buf, sizeof(buf));printf("%s", buf);return 0;
}
test.txt
hello world!
运行效果:

上述的例子中,定义一个大小为100字节的数组buf,一次性读取文件test.txt中的内存,并保存到buf里面,然后打印。该代码存在的问题是:假如文件test.txt中的内容非常多,超过数组的最大容量(100个字节),则超出数组容量外(超过100个字节之外)的数据会丢失。针对该问题我们可以尝试将上述代码优化为例子2。
例子2:
我们将例子1中的语句 char buf[100] = { 0 }; 修改为:char buf[nFileSize] = { 0 };
结果编译报错了:

在例子2中,我们尝试将数组buf的大小定义为要读取的文件的大小。很明显,这样是不行的,因为定义数组的时候,数组的大小必须确定,并且得是整型。我们继续优化代码。
例子3:
main.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <windows.h>// 通过stat结构体 获得文件大小,单位字节
size_t getFileSize1(const char* fileName) {if (fileName == NULL) {return 0;}// 这是一个存储文件(夹)信息的结构体,其中有文件大小和创建时间、访问时间、修改时间等struct stat statbuf;// 提供文件名字符串,获得文件属性结构体stat(fileName, &statbuf);// 获取文件大小size_t filesize = statbuf.st_size;return filesize;
}int main()
{const char *fileName = "test.txt";std::ifstream ifs(fileName);int nFileSize = getFileSize1(fileName);std::vector<char> vecBuf(nFileSize);ifs.read(&vecBuf[0], vecBuf.size());for (const auto& e : vecBuf){std::cout << e;}return 0;
}
运行效果如下:

例子3使用了vector<char>,所以可以在程序运行过程中调整大小(可以用resize()调整vector大小)。从而解决例子2中的问题。可能有些朋友会说用方法②“使用malloc/new动态分配内存”,不一样可以吗?确实是可以。但是vector<char>相当于对malloc/new进行了一层封装,使用起来更方便。而且不用手动调用delete函数释放内存,避免内存泄漏。
(二)跟方法②相比,vector<char>提供了各种方法
使用vector::reserve预分配内存
使用vector::size的记录缓冲区位置
使用vector::resize增长/清除缓冲区
使用&your_vector[0]转换为C缓冲区
使用vector::swap转换缓冲区所有权
例子4:
int bufsize = 4096;
char *pBuf = new char[bufsize];
int recv = read(sock, pbuf, bufsize)
例子4是一个网络接收的小demo。可以看到使用new的方式,需要额外增加一个变量bufsize来存贮缓冲区的大小。我们可以用vector<char>优化如下:
例子5:
std::vector<char> buf(4096); // create buffer with preallocated size
int recv = read( sock, &buf[0], buf.size() );
可以看到vector已经提供了size()方法来记录缓冲区的大小,不需要再额外增加变量了。所以使用vector<char>更方便,而且离开作用域自动释放内存,不需要手动delete,更安全。
(三)跟方法③相比,vector<char>可以存贮二进制数据
例子6:
main.cpp
#include <iostream>
#include <vector>
#include <string>using namespace std;int main()
{string strBuf = "abc\0ef";cout << strBuf << endl;std::vector<char> vecBuf = { 'a', 'b', 'c', '\0', 'e', 'f'};for (const auto& e : vecBuf){std::cout << e;}return 0;
}
运行效果如下:

可以看到使用std::string丢失了'\0'之后的数据,但是vector<char>不会。所以std::string只能存贮字符串,不能存贮二进制数据。二进制数据中可能会包含0x00(即:'\0'),刚好是字符串结束标志,使用std::string会有截断问题。所以对于二进制数据的保存(比如保存图片,网络接收)我们得要用vector<char>,不要用string。
三、总结
综上所述。我们首选vector<char>作为输入缓冲区。
参考:
What is the advantage of using vector<char> as input buffer over char array?
How do I use vector as input buffer for socket in C++
A more elegant way to use recv() and vector<unsigned char>
What are differences between std::string and std::vector<char>?
相关文章:
使用vector<char>作为输入缓冲区
一、引言 当我们编写代码:实现网络接收、读取文件内容等功能时,我们往往要在内存中开辟一个输入缓冲区(又名:input buffer/读缓冲区)来存贮接收到的数据。在C里面我们可以用如下方法开辟输入缓冲区。 ①使用C语言中的数组&#x…...
自己在网站搭建用到的一些网站
背景 以后可能很少做网站类的项目了,所以做个简单总结,把自己的一些经历和一些小工具做个记录 域名和主机 https://www.godaddy.com/zh-sg, 我之前的基本都是国际会议型的网站,所以就在gadaddy上买了主机和域名。目标群体在国内可以考虑腾…...
XLSReadWriteII5 Color 颜色l的调用和使用
XLSReadWriteII5 Color 颜色l的调用和使用 一、色彩三原色 自然界,颜色是由红、绿、蓝三色组成,人眼的可见的颜色,可以通过红、绿、蓝三色按照不同的比例合成产生。 任意一种颜色由这三种原色按照一定的比例混合出来。 二、Windows系…...
RT-Thread SP使用教程
RT-Thread SPI 使用教程 实验环境使用的是正点原子的潘多拉开发板。 SPI从机设备使用的是BMP280温湿度大气压传感器。 使用RT-Thread Studio搭建基础功能。 1. 创建工程 使用RT-Thread Studio IDE创建芯片级的工程。创建完成后,可以直接编译下载进行测试。 2.…...
LeetCode 2363. 合并相似的物品
给你两个二维整数数组 items1 和 items2 ,表示两个物品集合。每个数组 items 有以下特质: items[i] [valuei, weighti] 其中 valuei 表示第 i 件物品的 价值 ,weighti 表示第 i 件物品的 重量 。 items 中每件物品的价值都是 唯一的 。 请你…...
numpy 中常用的数据保存、fmt多个参数
在经常性读取大量的数值文件时(比如深度学习训练数据),可以考虑现将数据存储为Numpy格式,然后直接使用Numpy去读取,速度相比为转化前快很多 一、保存为二进制文件(.npy/.npz) (1)numpy.save(file, arr, allow_pickleTrue, fix_importsTrue) file:文件名…...
从0到1一步一步玩转openEuler--19 openEuler 管理服务-特性说明
文章目录19 管理服务-特性说明19.1 更快的启动速度19.2 提供按需启动能力19.3 采用cgroup特性跟踪和管理进程的生命周期19.4 启动挂载点和自动挂载的管理19.5 实现事务性依赖关系管理19.6 与SysV初始化脚本兼容19.7 能够对系统进行快照和恢复19 管理服务-特性说明 19.1 更快的…...
23美赛E题:光污染(ICM)完整思路Python代码
问题E(综合评价与仿真题):光污染(ICM) 背景 光污染用于描述过度或不良使用人造光。我们称之为光污染的一些现象包括光侵入、过度照明和光杂波。在大城市,太阳落山后,这些现象最容易在天空中看到;然而,它们也可能发生在更偏远的地区。 光污染会改变我们对夜空的看法,…...
快速排序的描述以及两种实现方案
一、快速排序描述 每一轮排序选择一个基准点(pivot)进行分区 1.1. 让小于基准点的元素的进入一个分区,大于基准点的元素的进入另一个分区 1.2. 当分区完成时,基准点元素的位置就是其最终位置在子分区内重复以上过程,直…...
算力引领 数“聚”韶关——第二届中国韶关大数据创新创业大赛圆满收官
为进一步促进数字经济领域创新创业发展,推动国家数据中心集群建设,构建大数据领域资源专业平台,促进大湾区大数据科技成果和创新创业人才转化落地,为韶关大数据领域创新型产业集群的打造、大数据科技成果和创新创业人才的转化落地…...
MySQL 记录锁+间隙锁可以防止删除操作而导致的幻读吗?
文章目录什么是幻读?实验验证加锁分析总结什么是幻读? 首先来看看 MySQL 文档是怎么定义幻读(Phantom Read)的: The so-called phantom problem occurs within a transaction when the same query produces different sets of r…...
【分库分表】企业级分库分表实战方案与详解(MySQL专栏启动)
📫作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建设优化,文章内容兼具广度、深度、大厂技术方案,对待技术喜欢推理加验证,就职于…...
(考研湖科大教书匠计算机网络)第五章传输层-第五节:TCP拥塞控制
获取pdf:密码7281专栏目录首页:【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一:拥塞控制概述二:拥塞控制四大算法(1)慢开始和拥塞避免A:慢启动(slow start)…...
13.使用自动创建线程池的风险,要自己创建为好
自动创建线程池就是直接调用 Executors去new默认的那几个线程池,但是会出现一定的风险,线程池里面会用到队列,也会跟线程池自身有关,所以要从队列和线程池两个方面去解析。 1.了解线程池的队列 线程池的内部结构主要由四部分组成…...
【项目设计】—— 负载均衡式在线OJ平台
目录 一、项目的相关背景 二、所用技术栈和开发环境 三、项目的宏观结构 四、compile_server模块设计 1. 编译服务(compiler模块) 2. 运行服务(runner模块) 3. 编译并运行服务(compile_run模块) 4…...
Docker学习笔记
1:docker安装步骤Linux 2:docker安装步骤Windows 3:docker官方文档 4:docker官方远程仓库 docker常用命令 1: docker images----查看docker中安装的镜像 2: docker pull nginx------在docker中安装Nginx镜…...
【爬虫理论实战】详解常见头部反爬技巧与验证方式 | 有 Python 代码实现
以下是常见头部反爬技巧与验证方式的大纲: User-Agent 字段的伪装方式,Referer 字段的伪装方式,Cookie 字段的伪装方式。 文章目录1. ⛳️ 头部反爬技巧1.1. User-Agent 字段&User-Agent 的作用1.2. 常见 User-Agent 的特征1.3. User-Age…...
基于SpringBoot+Vue的鲜花商场管理系统
【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行! 博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、…...
华为OD机试 - 静态扫描最优成本(JS)
静态扫描最优成本 题目 静态扫描快速识别源代码的缺陷,静态扫描的结果以扫描报告作为输出: 文件扫描的成本和文件大小相关,如果文件大小为 N ,则扫描成本为 N 个金币扫描报告的缓存成本和文件大小无关,每缓存一个报告需要 M 个金币扫描报告缓存后,后继再碰到该文件则不…...
多层感知机
多层感知机理论部分 本文系统的讲解多层感知机的pytorch复现,以及详细的代码解释。 部分文字和代码来自《动手学深度学习》!! 目录多层感知机理论部分隐藏层多层感知机数学逻辑激活函数1. ReLU函数2. sigmoid函数3. tanh函数多层感知机的从零…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...
Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
