1. 程式人生 > >Effective_STL 學習筆記(十六) 如何將 vector 和 string 的數據傳給遺留的API

Effective_STL 學習筆記(十六) 如何將 vector 和 string 的數據傳給遺留的API

lar 內存分配 修改 叠代 元素 amp const 兼容 con

已經存在的遺留的 C 風格 API 接受的是數組和 char* 指針,這樣的 API 函數還將會存在很長時間,如果我們要有效使用 STL 的話,就必須和它們和平共處。

如果有一個 vector 對象 v,而你需要一個指向 v 中數據的指針,以使得它可以被當作一個數組,只要 &v[0] 就可以了。對於 string 對象 s,相應的使用 s.c_str()

1   void doSomething( const int* pInts, size_t numInts );
2   doSomething( &v[0], v.size() );
3   void doSomething( const
char* pString ); 4   doSomething( s.c_str() );

對於 vector 使用不要使用 v.begin() 代替 &v[0],v.begin() 是叠代器,不是指針,一定要使用的話,鍵入&*v.begin()

string 的成員函數 c_str() 返回一個按 C 風格設計的指針,指向 string 的值

兩種形式下,指針都被傳遞為指向 const 的指針

1     void doSomething( const int* pInts, size_t numInts );
2     void doSomething( const
cahr* pString );

vector 和 string 只能傳給只讀取而不修改它的API,對於 string 來說是唯一可做的,對於 vector 相對靈活一點。

如果想用 C 風格API返回的元素初始化一個 vector,可以利用 vector 和數組潛在的內存分配兼容性將存儲 vector 的元素空間傳給API函數:

1   // C API:此函數需要一個指向數組的指針,數組最多有 arraySize 個 double
2   // 而且會對數組寫入數據。它返回寫入的 double 數,不會大於 arraySize
3   size_t fillArray( double* pArray, size_t arraySize );
4   vector<double> vd( maxNumDoubles );        // 建立一個 vector,大小是 maxNumDoubles 5   vd.resize( fillArray( &vd[0], vd.size() ) );  // 寫入vd,然後調整 vd 的大小為fillArray

這個技巧只能工作於vector,因為只有vector承諾了與數組具有相同的潛在內存分布。

如果想用C風格 API 初始化 string 對象,只要讓 API 將數據放入一個 vector<char>,然後再從 vector 中將數據拷到 string:

1   // C API:此函數需要一個指向數組的指針,數組最多有 arraySize 個 char
2   // 而且會對數組寫入數據。它返回寫入的 char 數,不會大於 arraySize
3   size_t fillString( char* pArray, size_t arraySize );
4   vector<char> vc( maxNumChars );        // 建立一個 vector
5   size_t charsWritten = fillString( &vc[0], vc.size() );// 讓 fillString 把數據寫入 vc
6   string s( vc.begin(), vc.end() + charsWritten );    // 從 vc 通過範圍構造函數拷貝數據到s

事實上,讓 C 風格 API 把數據放入一個 vector,然後拷到你實際想要的 STL 容器中總是有效的:

1   size_t fillString( double* pArray, size_t arraySize );
2   vector<double> vd( maxNumDoubles ); 
3   vd.resize( fillArray( &vd[0], vd.size() ) );
4 
5   deque<double> d( vd.begin(), vd.end() );  // 拷貝數據到 deque
6   list<double> d( vd.begin(), vd.end() );   // 拷貝數據到 list
7   set<double> d( vd.begin(), vd.end() );   // 拷貝數據到 set

此外,對於 vector 和 string 以外的 STL 容器如何將他們的數據傳給 C 風格 API。只要將容器的每個數據拷到 vector,然後將它們傳給API:

  void doSomething( const int* pints, size_t numInts );
  set<int> intSet;
  . . .
  vector<int> v( intSet.begin(), intSet.end() );  // 拷貝 set 數據到 vector
  if( !v.empty() )              
    doSomething( &v[0], v.size() );    // 傳遞數據到 API

Effective_STL 學習筆記(十六) 如何將 vector 和 string 的數據傳給遺留的API