1. 程式人生 > >std::string與char*之臨時緩衝區

std::string與char*之臨時緩衝區

c++檔案讀取流程如下:

ifstream ifs(srcFile, ifstream::binary);
if(ifs.is_open())
{
    ifs.seekg(0, ifs.end);
    long filesize = ifs.tellg(); 
    ifs.seekg (0);

    char* fileBuffer = new char[filesize]; //分配記憶體緩衝區
    ifs.read(fileBuffer, filesize); //讀取檔案內容到緩衝區
    ifs.close();

    //do sth. with fileBuffer
delete []fileBuffer; //release memory }

整個流程中記憶體的分配和讀沒什麼問題。如果需要對fileBuffer的內容做些字串處理相關的工作,因std::string操作比較方便,通常會先把fileBuffer轉化為std::string,然後再刪掉fileBuffer,如下

char* fileBuffer = new char[filesize]; //分配記憶體緩衝區
ifs.read(fileBuffer, filesize); //讀取檔案內容到緩衝區
ifs.close();

std::string strBuffer(fileBuffer);
delete
[]fileBuffer; //release memory //do sth. with strBuffer...

這麼做其實也沒什麼問題,風險無非有兩個,一是忘了delete []fileBuffer,二是記憶體緩衝區可能在建立strBuffer時翻了一倍,雖然std::string在設計時考慮到了copy on write,但風險依然是存在的。

為了解決上面若有若無的風險,需要使用c++程式設計中常用的模式RAII即“資源獲取就是初始化”,用物件來管理資源,如下:

std::string strBuffer(filesize, 0);//分配記憶體緩衝區
char* fileBuffer = &*strBuffer.begin(); //獲取分配記憶體緩衝區的首地址
ifs.read(fileBuffer, filesize); //讀取內容到緩衝區 ifs.close(); //do sth. with strBuffer or fileBuffer...

另外,C++11後調整了std::string,收緊了相關許可權,比如:

常量字串必須是const只讀的

char* str = "this is test string";  //wrong
const char* str = "this is a test string"; //right

const char* 物件不能賦值給 char*

std::string str = "this is test string";
char* szStr = str.c_str(); //wrong
char* szStr = str.data();  //wrong
const char* szStr = str.c_str(); //right
const char* szStr = str.data();  //right

如果需要把std::string賦值給char*,即取得std::string物件的可讀寫首地址,需要轉變思路

先獲取首元素,然後對其取地址

std::string str = "this is a string";
char* szStr = &*str.begin();
char* szStr = &str[0];

這樣對szStr的操作也對str生效了。