看板 C_and_CPP 關於我們 聯絡資訊
嗯,雖然用了「問題」當標題,但這篇其實是一整個自問自答,而且我相信很多 人早就知道答案了。 想像一下,如果我們要把某個文字檔的內容直接讀進某個 C++ string 中,大概 會用如下的方法: string ReadFile(const char* filename) { ifstream fin(filename, ios::binary); fin.seekg(0, ios::end); size_t len = fin.tellg(); // get the file size fin.seekg(0, ios::beg); vector<char> buf(len); // allocate a buffer for fin.read() fin.read(&buf[0], len); return string(&buf[0], len); } 因為 vector 保證它的儲存空間是連續的,所以我們可以用 vector 來當作 fin.read 的 buffer。不過這樣勢必要多一次額外的資料複製。我們能不能 改成這樣呢: string ReadFile(const char* filename) { ifstream fin(filename, ios::binary); fin.seekg(0, ios::end); size_t len = fin.tellg(); // get the file size fin.seekg(0, ios::beg); string buf(len, 0); // allocate a buffer for fin.read() fin.read(&buf[0], len); return buf; } 直接拿 string 的內部空間來接收 fin.read 的資料。而這樣做是否可行,取決 於 string 內部是否使用連續的空間來儲存字串。 根據一陣子的 google 之後,結論是這樣的: 1. C++ 標準是沒有很明確地說 std::string 的空間必須連續,但你很難實作出 一個符合標準卻又不使用連續空間的 std::string。事實上目前所有的實作 都使用連續空間。 2. 未來的 C++0x 標準會明確要求 std::string 的儲存空間必須連續。 3. 事實上在舊的 C++98 標準中也沒有嚴格規定 std::vector 使用連續的儲存 空間,不過發生的問題就如同 std::string 一樣:很難實作出空間不連續 卻又符合標準的 std::vector、既存的實作品都使用連續空間、不使用連續 空間會讓 client code 用起來很不方便等等。最後到了 C++03 就明確要求 std::vector 須要使用連續儲存空間了。 參考連結: * Is std::string’s storage contiguous? http://ppt.cc/n0RP * Cringe not: Vectors are guaranteed to be contiguous http://ppt.cc/,0Py * C++ Standard Library Defect Report: 530. Must elements of a string be contiguous? http://ppt.cc/UR_6 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.112.29.108
VictorTom:先推, 晚點再回來看XD 04/13 10:48
ykjiang:不是有 c_str 可用嗎? 04/13 12:16
littleshan:c_str 只能讀不能寫唷 *.< 04/13 12:24
ilovebbs:不過會有什麼影響啊?連不連續的問題?@@? 04/13 12:55
tomore:c_str不能寫嗎?我用過怎是可以寫不能讀 04/13 13:06
holymars:大概是你用到外星科技版的實作品了 04/13 13:07
holymars:c_str() 回傳型態是"const char*" 04/13 13:08
HudsonE:嗯, 如果不用連續空間來實作, 各種效益上都比較差 04/13 14:53
ilovebbs:喔喔..可以理解..Thx~ 04/13 14:55
jacobcrab:為什麼不用 ostringstream 物件, 然後把 fin的資料 '<<' 04/13 16:06
jacobcrab:進去,最後直接回傳 ostrm.str() 就好了?這樣比較簡潔吧? 04/13 16:07
littleshan:遇到這問題通常都是為了包裝 C-API 04/13 16:15
littleshan:舊式的 C API 在回傳 string 時,往往會要求使用者傳入 04/13 16:23
littleshan:一塊 char* 的 buffer 以及這塊 buffer 的大小,然後 04/13 16:24
littleshan:該函式再把欲回傳的 string 填入這塊 buffer 中。 04/13 16:24
littleshan:本來想拿一段 OpenCL 的 code 當 sample,不過怕模糊 04/13 16:26
littleshan:焦點,就改成以讀檔當作 sample 了。 04/13 16:27
yoco315:sgi rope 不知道有沒有符合 std::string 的介面.. 04/13 18:52
littleshan:std::string 規定 operator[](i) 要回傳 data()[i] 04/13 19:49
littleshan:而且 operator[](i) 要能夠回傳 non-const reference 04/13 19:50
littleshan:所以看來 rope 是不符合 std::string 的 04/13 19:50
pichubaby:這樣做之前有需要先resize(len)嗎? size()會不會有問題? 04/14 00:18
littleshan:string(len, 0) 會建構一份長度為 len,內容為0的字串 04/14 09:05