条款16: 如何将vector和string的数据传给遗留的API

来源:互联网 发布:英虎网络股份有限公司 编辑:程序博客网 时间:2024/06/05 23:44

将vector和string的数据传给遗留的API

C风格API接受的是数组和char*指针,而不是vector和string对象。

如果你有一个vector对象v,而你需要得到一个指向v中数据的指针,以使得它可以被当作一个数组,只要使用&v[0]就可以了。

对于string对象s,相应的咒语是简单的s.c_str()

例子:传递v给这样的C风格的API:

void doSomething(const int* pInts, size_tnumInts);

我们可以这么做:

doSomething(&v[0], v.size());

唯一的问题就是,如果v是空的。如果这样的话,v.size()是0,而&v[0]试图产生一个指向根

本就不存在的东西的指针。这不是件好事。其结果未定义。

较安全的方法是这样:

if(!v.empty()) {

doSomething(&v[0],v.size());

}

用v.begin()代替&v[0]:对于vector,其迭代器实际上是指针。那经常是正确的并不总是如此,你不该依赖于此。【条款50】

begin的返回类型是iterator,而不是一个指针,当你需要一个指向vector内部数据的指针时绝不该使用begin。如果你基于某些原因决定键入v.begin(),就应该键入&*v.begin(),因为这将会产生和&v[0]相同的指针。

(译注:在VC6中,如果用v.begin()代替&v[0],编译器不会说什么,但在VC7和g++中这么做的话,就会引发一个编译错误)

类似从vector上获取指向内部数据的指针的方法,对string不是可靠的,因为(1)string中的数据并没有保证被存储在独立的一块连续内存中,

(2)string的内部表示形式并没承诺以一个null字符结束。

voiddoSomething(const char *pString);

像这样:

doSomething(s.c_str());

即使是字符串的长度为0,它都能工作。在那种情况下,c_str将返回一个指向null字符的指针。

即使字符串内部自己内含null时,它同样能工作。但是,如果真的这样,doSomething很可能将第一个内含的null解释为字符串结束

如果你想用C风格API返回的元素初始化一个vector

size_t fillArray(double*pArray, size_t arraySize);

vector<double>vd(maxNumDoubles); // 建立一个vector,

// 它的大小是maxNumDoubles

vd.resize(fillArray(&vd[0],vd.size())); // 让fillArray把数据写入vd,然后调整//vd的大小

deque<double> d(vd.begin(), vd.end()); // 拷贝数据到deque

list<double> l(vd.begin(), vd.end()); // 拷贝数据到list

set<double> s(vd.begin(), vd.end()); // 拷贝数据到set

vector和string以外的STL容器如何将它们的数据传给C风格API。只要将容器的每个数据拷到vector,然后将它们传给API:

void doSomething(const int* pints, size_t numInts); //C API (同上)

set<int> intSet; // 保存要传递给API数据的set

...

vector<int> v(intSet.begin(), intSet.end()); // 拷贝set数据到vector

if (!v.empty()) doSomething(&v[0], v.size()); // 传递数据到API

用来自C风格API的数据初始化string对象

只要让API将数据放入一个vector<char>,然后从vector中将数据拷到string:

size_t fillString(char*pArray, size_t arraySize);

vector<char>vc(maxNumChars); // 建立一个vector,

// 它的大小是maxNumChars

size_t charsWritten =fillString(&vc[0], vc.size()); // 让fillString把数据写入vc

string s(vc.begin(), vc.begin()+charsWritten);// 从vc通过范围构造函数
0 0