有时需要支持 C 的接口,但这并不复杂。

对于 vector 来讲, \(v[0]\) 的地址 \(\&v[0]\) 即可作为数组指针传递给 C API:

 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]\) ,即:

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

String 对象没有要求保证所有字符串都存放在连续的内存空间,而且 string 内部不会保证内存中对象会以 NULL 结尾,上面对 \(\&v[0]\) 的方法对 string 不一定行得通,对 string 来讲,我们应该使用它提供的成员函数: c_str() , 下面的代码中无需检查 ss 是否为空,因为如果 ss 为空, ss.c_str() 会返回 NULL

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() 来改变容器的大小:

// 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 来初始化 string

// 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:

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);

Effective STL 学习笔记 Item 16:vector, string & C API的更多相关文章

  1. Effective STL 学习笔记: 多用 vector & string

    Effective STL 学习笔记: 多用 vector & string 如果可能的话, 尽量避免自己去写动态分配的数组,转而使用 vector 和 string . 原书作者唯一想到的一 ...

  2. Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据

    Effective STL 学习笔记 Item 34: 了解哪些算法希望输入有序数据 */--> div.org-src-container { font-size: 85%; font-fam ...

  3. Effective STL 学习笔记 Item 30: 保证目标区间足够大

    Effective STL 学习笔记 Item 30: 保证目标区间足够大 */--> div.org-src-container { font-size: 85%; font-family: ...

  4. Effective STL 学习笔记 Item 26: Prefer Iterator to reverse_iterator and const_rever_itertor

    Effective STL 学习笔记 Item 26: Prefer Iterator to reverse_iterator and const_rever_itertor */--> div ...

  5. Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value

    Effective STL 学习笔记 Item 38 : Design functor classes for pass-by-value */--> div.org-src-container ...

  6. Effective STL 学习笔记 Item 21:Comparison Function 相关

    Effective STL 学习笔记 Item 21:Comparison Function 相关 */--> div.org-src-container { font-size: 85%; f ...

  7. Effective STL 学习笔记 Item 18: 慎用 vector<bool>

    vector<bool> 看起来像是一个存放布尔变量的容器,但是其实本身其实并不是一个容器,它里面存放的对象也不是布尔变量,这一点在 GCC 源码中 vector<bool> ...

  8. Effective STL 学习笔记 Item 17: Swap Trick

    假设有若干对象存于一个 vector 中: class Widget; vector<Widget> vw; 后来由于某些原因,从该容器中删除了若干对象(参考erase-remove id ...

  9. Effective STL 学习笔记: Item 22 ~ 24

    Effective STL 学习笔记: Item 22 ~ 24 */--> div.org-src-container { font-size: 85%; font-family: monos ...

随机推荐

  1. ASP.NET MVC 3 常用

    http://blog.csdn.net/churujianghu/article/details/7297358 1.ASP.NET MVC 3 如何去除默认验证 这个默认验证是在web.confi ...

  2. STM32 ------ HardFault_Hander 中断函数

    1.数组越界(对数组赋值) 正常情况,数组越界会进入 HardFault_Hander 中断函数的无线循环. 避免数组越界的一个方法是:每次使用数组前,检查要放入数据的数据长度是否大于数组长度,大于则 ...

  3. 初学SQL语句练习1

    --[1 ]查询出每个月倒数第三天受雇的所有员工SELECT * FROM EMP WHERE HIREDATE=LAST_DAY(HIREDATE)-2; --[2 ]找出早于30 年前受雇的员工S ...

  4. Oracle的基本语法,存储函数及触发器

    1.PL/SQL    PL/SQL是Oracle对 ql语言的过程化扩展,指在 SQL 命令语言中增加了过程处理语句,使SQL语言具有过程处理能力.把 SQL 语言的数据操纵能  力与过程语言的数据 ...

  5. python字符中加入变量

    有时候,我们需要在字符串中加入相应的变量,以下提供了几种字符串加入变量的方法: 1.+ 连字符 name = 'zhangsan' print('my name is '+name) #结果为 my  ...

  6. iview组件 eslint校验出错 Parsing error: x-invalid-end-tag

    如下: 解决: 在.eslintrc.js文件中加上: rules: { // allow async-await 'generator-star-spacing': 'off', // allow ...

  7. highCharts参数实例解释

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  8. Java压缩/解压.zip、.tar.gz、.tar.bz2(支持中文)

    本文介绍Java压缩/解压.zip..tar.gz..tar.bz2的方式. 对于zip文件:使用java.util.zip.ZipEntry 和 java.util.zip.ZipFile,通过设置 ...

  9. ASP.NET对无序列表批量操作的三种方法

    在网页开发中,经常要用到无序列表.事实上在符合W3C标准的div+css布局中,无序列表被大量使用,ASP.NET虽然内置了BulletedList控件,用于创建和操作无序列表,但感觉不太好用.本篇介 ...

  10. 38、使用IO流进行文件拷贝

    使用IO流进行文件拷贝 需求:在项目的根目录里面创建一个java.txt的文件,然后将这个文件拷贝到file文件夹里面并且重命名为good.txt文件先以流的方式将java.txt文件读取到内存中,然 ...