如何将vector 和 string 传递给 类C的API

来源:互联网 发布:月相模拟软件 编辑:程序博客网 时间:2024/06/06 08:40

一、vector

vector<int> v;

对于这样的类C的API: 

void doSomething(const int* pInts, size_t numInts);

if (!v.empty()) {

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


如果你在一个不好的环境中,你可能会碰到一些半吊子的人物,他们会告诉你说可以用v.begin()代替&v[0],因为(这些讨厌的家伙将会告诉你)begin返回指向vector内部的迭代器,而对于vector,其迭代器实际上是指针。那经常是正确的,并不总是如此,你不该依赖于此。begin的返回类型是iterator,而不是一个指针,当你需要一个指向vector内部数据的指针时绝不该使用begin。如果你基于某些原因决定键入v.begin(),就应该键入&*v.begin(),因为这将会产生和&v[0]相同的指针,这样可以让你有更多的打字机会,而
且让其他要弄懂你代码得人感觉到更晦涩。坦白地说,如果你正在和告诉你使用v.begin()代替&v[0]的人打交道的话,你该重新考虑一下你的社交圈了。(译注:在VC6中,如果用v.begin()代替&v[0],编译器不会说什么,但在VC7和g++中这么做的话,就会引发一个编译错误)


二、string

string s;

void doSomething(const char *pString);

doSomething(s.c_str());

即使是字符串的长度为0,它都能工作。在那种情况下,c_str将返回一个指向null字符的指针。即使字符串内部自己内含null时,它同样能工作。但是,如果真的这样,doSomething很可能将第一个内含的null解释为字符串结束。string对象不在意是否容纳了结束符,但基于char*的C风格API在意。


三、C风格API返回的元素初始化一个vector
// C API:此函数需要一个指向数组的指针,数组最多有arraySize个double
// 而且会对数组写入数据。它返回写入的double数,不会大于arraySize
size_t fillArray(double *pArray, size_t arraySize);
vector<double> vd(maxNumDoubles);                      // 建立一个vector,
                                                        // 它的大小是maxNumDoubles
vd.resize(fillArray(&vd[0], vd.size()));                        // 让fillArray把数据
                                                        // 写入vd,然后调整vd的大小
                                                        // 为fillArray写入的元素个数


四、C风格API的数据初始化string对象

// C API:此函数需要一个指向数组的指针,数组最多有arraySize个char
// 而且会对数组写入数据。它返回写入的char数,不会大于arraySize
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通过范围构造函数

 // 拷贝数据到s


五、其他容器

1、事实上,让C风格API把数据放入一个vector,然后拷到你实际想要的STL容器中的主意总是有效的: 
size_t fillArray(double *pArray, size_t arraySize);             // 同上
vector<double> vd(maxNumDoubles);                            // 一样同上
vd.resize(fillArray(&vd[0], vd.size()));


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


2、这也提示了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

0 0