汽車網(wǎng)站建設(shè)參考文獻(xiàn)開題報(bào)告在線視頻用什么網(wǎng)址
一、引言
? 當(dāng)我們編寫代碼:實(shí)現(xiàn)網(wǎng)絡(luò)接收、讀取文件內(nèi)容等功能時(shí),我們往往要在內(nèi)存中開辟一個(gè)輸入緩沖區(qū)(又名:input buffer/讀緩沖區(qū))來存貯接收到的數(shù)據(jù)。在C++里面我們可以用如下方法開辟輸入緩沖區(qū)。
①使用C語言中的數(shù)組:
char buf[100] = {0};
②使用malloc/new動(dòng)態(tài)分配內(nèi)存:
char *pBuf = new char[100];
③使用std::string
string sBuf;
④使用vector<char> /?vector<unsigned char>
vector<char> vecBuf(100);
在這里面推薦使用方法④作為輸入緩沖區(qū)。方法①在棧中開辟空間,對(duì)于大數(shù)組可能會(huì)有棧內(nèi)存不夠的問題。方法②在堆上分配內(nèi)存,但是使用完需要程序員自行手動(dòng)釋放(delete?pBuf),而且需要一個(gè)額外的變量記錄申請(qǐng)空間的大小。方法③只能處理字符串,不能處理二進(jìn)制數(shù)據(jù)。下面具體闡述使用vector<char>作為輸入緩沖區(qū)的優(yōu)勢。
二、使用vector<char>作為輸入緩沖區(qū)的優(yōu)勢
(一)跟方法①相比,vector<char>可以在程序運(yùn)行時(shí)調(diào)整大小
例子1:
main.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <windows.h>// 通過stat結(jié)構(gòu)體 獲得文件大小,單位字節(jié)
size_t getFileSize1(const char* fileName) {if (fileName == NULL) {return 0;}// 這是一個(gè)存儲(chǔ)文件(夾)信息的結(jié)構(gòu)體,其中有文件大小和創(chuàng)建時(shí)間、訪問時(shí)間、修改時(shí)間等struct stat statbuf;// 提供文件名字符串,獲得文件屬性結(jié)構(gòu)體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!
運(yùn)行效果:
上述的例子中,定義一個(gè)大小為100字節(jié)的數(shù)組buf,一次性讀取文件test.txt中的內(nèi)存,并保存到buf里面,然后打印。該代碼存在的問題是:假如文件test.txt中的內(nèi)容非常多,超過數(shù)組的最大容量(100個(gè)字節(jié)),則超出數(shù)組容量外(超過100個(gè)字節(jié)之外)的數(shù)據(jù)會(huì)丟失。針對(duì)該問題我們可以嘗試將上述代碼優(yōu)化為例子2。
例子2:
我們將例子1中的語句 char buf[100] = { 0 }; ?修改為:char buf[nFileSize] = { 0 };
結(jié)果編譯報(bào)錯(cuò)了:?
在例子2中,我們嘗試將數(shù)組buf的大小定義為要讀取的文件的大小。很明顯,這樣是不行的,因?yàn)槎x數(shù)組的時(shí)候,數(shù)組的大小必須確定,并且得是整型。我們繼續(xù)優(yōu)化代碼。
例子3:
main.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include <windows.h>// 通過stat結(jié)構(gòu)體 獲得文件大小,單位字節(jié)
size_t getFileSize1(const char* fileName) {if (fileName == NULL) {return 0;}// 這是一個(gè)存儲(chǔ)文件(夾)信息的結(jié)構(gòu)體,其中有文件大小和創(chuàng)建時(shí)間、訪問時(shí)間、修改時(shí)間等struct stat statbuf;// 提供文件名字符串,獲得文件屬性結(jié)構(gòu)體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;
}
運(yùn)行效果如下:
例子3使用了vector<char>,所以可以在程序運(yùn)行過程中調(diào)整大小(可以用resize()調(diào)整vector大小)。從而解決例子2中的問題??赡苡行┡笥褧?huì)說用方法②“使用malloc/new動(dòng)態(tài)分配內(nèi)存”,不一樣可以嗎?確實(shí)是可以。但是vector<char>相當(dāng)于對(duì)malloc/new進(jìn)行了一層封裝,使用起來更方便。而且不用手動(dòng)調(diào)用delete函數(shù)釋放內(nèi)存,避免內(nèi)存泄漏。
(二)跟方法②相比,vector<char>提供了各種方法
使用vector::reserve預(yù)分配內(nèi)存
使用vector::size的記錄緩沖區(qū)位置
使用vector::resize增長/清除緩沖區(qū)
使用&your_vector[0]轉(zhuǎn)換為C緩沖區(qū)
使用vector::swap轉(zhuǎn)換緩沖區(qū)所有權(quán)
例子4:
int bufsize = 4096;
char *pBuf = new char[bufsize];
int recv = read(sock, pbuf, bufsize)
例子4是一個(gè)網(wǎng)絡(luò)接收的小demo??梢钥吹绞褂胣ew的方式,需要額外增加一個(gè)變量bufsize來存貯緩沖區(qū)的大小。我們可以用vector<char>優(yōu)化如下:
例子5:
std::vector<char> buf(4096); // create buffer with preallocated size
int recv = read( sock, &buf[0], buf.size() );
可以看到vector已經(jīng)提供了size()方法來記錄緩沖區(qū)的大小,不需要再額外增加變量了。所以使用vector<char>更方便,而且離開作用域自動(dòng)釋放內(nèi)存,不需要手動(dòng)delete,更安全。
(三)跟方法③相比,vector<char>可以存貯二進(jìn)制數(shù)據(jù)
例子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;
}
運(yùn)行效果如下:
?可以看到使用std::string丟失了'\0'之后的數(shù)據(jù),但是vector<char>不會(huì)。所以std::string只能存貯字符串,不能存貯二進(jìn)制數(shù)據(jù)。二進(jìn)制數(shù)據(jù)中可能會(huì)包含0x00(即:'\0'),剛好是字符串結(jié)束標(biāo)志,使用std::string會(huì)有截?cái)鄦栴}。所以對(duì)于二進(jìn)制數(shù)據(jù)的保存(比如保存圖片,網(wǎng)絡(luò)接收)我們得要用vector<char>,不要用string。
三、總結(jié)
綜上所述。我們首選vector<char>作為輸入緩沖區(qū)。
參考:
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>?