Effective STL 學習筆記 Item 16:vector, string & C API

有時須要支持 C 的接口,但這並不複雜。html

對於 vector 來說, \(v[0]\) 的地址 \(\&v[0]\) 便可做爲數組指針傳遞給 C API:java

 1: // Legacy C API.
 2: extern void doSomething(const int* pInts, size_t numInts);
 3: 
 4: vector<int> v;
 5: // ...
 6: // Operations on v.
 7: // ...
 8: 
 9: if (!v.empty())
10: {
11:     doSomething(&v[0], v.size());
12: }

也許有人會說:能夠用 v.begin() 來替代 \(\&v[0]\), 但並不是永遠如此, v.begin() 返回的是一個迭,迭代器指向的對象的地址纔是真正的 \(\&v[0]\) ,即:c++

&*v.begin() == &v[0]

String 對象沒有要求保證全部字符串都存放在連續的內存空間,並且 string 內部不會保證內存中對象會以 NULL 結尾,上面對 \(\&v[0]\) 的方法對 string 不必定行得通,對 string 來說,咱們應該使用它提供的成員函數: c_str() , 下面的代碼中無需檢查 ss 是否爲空,由於若是 ss 爲空, ss.c_str() 會返回 NULLsql

13: // Legacy C API:
14: extern void doSomething(const char* str);
15: 
16: string ss;
17: // ...
18: // Do something with ss
19: // ...
20: 
21: doSomething(ss.c_str());

注意第 2 和第 14 行中 C API 中的 const 限定符,調用的函數不該該修改指針指向的內容,但若是咱們須要經過調用 C API 來初始化 vector 或 string,應該怎麼作?數組

對於 vector 來說, Item 14 提到,經過 reserve() 能夠預留出足夠的空間,並且是連續空間,這樣咱們能夠在調用 C API 進行初始化以前來分配好足夠空間,並在初始化以後調用 resize() 來改變容器的大小:bash

// C API: this function takes a pointer to an array of at most arraySize
// doubles and writes data to it. It returns the number of doubles written,
// which is never more than maxNumDoubles.
size_t fillArray(double *pArray, size_t arraySize);

vector<double> vd;
vd.reserve(maxNumDoubles);
vd.resize(fillArray(&vd[0], maxNumDoubles))

或者更簡單的:函數

vector<double> vd(maxNumDouble);
vd.resize(fillArray(&vd[0], vd.size()));

String 提供的 c_str() 指向的指針是隻讀的,不能將其傳給 C API 進行初始化,但咱們能夠經過前面提到的方法:將 vector<char> 的指針傳給 C API,而後再用這個 vector 來初始化 stringpost

// C API: this function takes a pointer to an array of at most arraySize
// chars and writes data to it. It returns the number of chars written,
// which is never more than maxNumChars.

size_t fillString(char* pArray, size_t arraySize);

vector<char> vc(maxNumChars);
size_t charsWritten = fillString(&vc[0], vc.size());
string s(vc.begin(), vc.begin()+charsWritten));

上面的這個技巧,能夠適用於任何的容器,例如若是咱們想用 C API 來初始化一個 set:this

size_t doSomething(int* pints, size_t numInts); // C API to initialize int array.
vector<int> v(maxNumInts); // This is media
size_t sz = doSomething(&v[0], v.size());
set<int> intSet(v.begin(), v.begin()+sz);
相關文章
相關標籤/搜索