• Effective STL 学习笔记 Item 16:vector, string & C API


    有时需要支持 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);
    
  • 相关阅读:
    [洛谷P1155] 双栈排序
    [洛谷P4315] 月下”毛景“树
    [洛谷P2486] [SDOI2011]染色
    [HNOI2010] 弾飞绵羊
    mysql注入总结
    cisco交换机实现端口聚合
    python为运维人员打造一个监控脚本
    复习ACCESS注入
    利用sfc文件构建网络渗透
    FTP站点设置
  • 原文地址:https://www.cnblogs.com/yangyingchao/p/3402097.html
Copyright © 2020-2023  润新知