作者littleshan (我要加入劍道社!)
看板C_and_CPP
標題[問題] std::string 的空間是否連續?
時間Tue Apr 13 10:08:33 2010
嗯,雖然用了「問題」當標題,但這篇其實是一整個自問自答,而且我相信很多
人早就知道答案了。
想像一下,如果我們要把某個文字檔的內容直接讀進某個 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