zoukankan      html  css  js  c++  java
  • STL学习笔记(二) vector和string

    条款13:vector、string优先于动态分配数组

    string是basic_string<char>的类型定义
    许多string的背后实现都采用了引用计数的技术,可以消除不必要的内存拷贝和不必要的字符拷贝

    条款14:使用 reserve 来避免vector容器不必要的重新分配

    vector和string的 realloc 的操作分为4部分:
    a.分配一块大小为当前容量的某个倍数的新内存,大多数实现中,vector和string的容量每次以2倍增长
    b.把容器的所有元素从旧的内存拷贝到新的内存中
    c.析构掉旧内存中的对象
    d.释放旧内存
    注:任何push、insert操作可能导致内存重分配.重分配之后原来的迭代器、指针、引用全部失效

    vector、string的4个成员函数:
    a.size():容器中现有多少个元素
    b.capacity():容器现分配的内存可以容纳的元素总数
    c.resize(vector::size_type n):强迫容器改变到包含n个元素的状态
    如果n小于当前size(),则容器尾部的元素将会被析构
    如果n小于当前capacity(),则通过默认构造函数创建的新元素被添加到容器的末尾
    如果n大于当前capacity(),则会重新分配内存
    d.reserve(vector::size_type n):强迫容器把它的容量capacity变为至少是n,前提是n不小于当前大小

    vector<int> vec;
    for (int i = 0; i < 1000; ++i) vec.push_back(i);    //导致10次重分配内存, log(1000)
    
    vector<int> vec;
    vec.reserve(1000);
    for (int i = 0; i < 1000; ++i) vec.push_back(i);    //循环过程中不会重分配内存

    大小(size)和容量(capacity)之间的关系使我们能够预知什么时候插入操作会导致重分配内存

    条款15:注意string实现的多样性

    string的值可能会被引用计数,也可能不会,很多实现在默认情况下使用引用计数技术
    string对象大小的范围可以是一个 char* 指针的大小的1倍到7倍
    不同的实现对字符内存的分配有不同的策略

    条款16:了解如何把 vector、string数据传给旧的 c—style API

    当需要vector容器首地址时(C API常常需要数组首地址)应该使用 &v[0],而不是v.begin() (begin()返回的是指向容器第一个元素的迭代器)
    当需要 char* 时,使用 str.c_str();

    标准STL容器与C API转换(利用vector容器与数组内存布局的兼容性)
    (1) C API 转到 STL容器

    size_t fillArray(double* pArray, size_t arraySize);
    vector<double> vec(maxNum);
    
    vec.resize(fillArray(&v[0], vd.size() ));  //将 C array数据拷贝到 vector容器
    deque<double> d(vec.begin(), vec.end());   //将 C array数据拷贝到 deque容器
    list<double> l(vec.begin(), vec.end() );   //将 C array数据拷贝到 list容器
    set<double> s(vec.begin(), vec.end() );    //将 C array数据拷贝到 set容器

    (2)STL容器 转到 C API

    set<double> s;
    vector<double> vec(s.begin(), s.end());
    void func(&s[0], s.size());
    条款17:使用"swap技巧"除去多余的容量

    vector容器只会自动扩充内存,不会自动缩减
    为了避免容器占用不再需要的内存,可以显示地从容器中去除多余的容量:

    vector<Widget> vec;
    vector<Widget>(vec).swap(vec);

    表达式 vector<Widget>(vec) 创建一个临时变量,这个变量是 vec变量的拷贝,相当于: vector<Widget> temp(vec);
    临时变量的拷贝是由拷贝构造函数完成的,因为 拷贝构造函数只为所拷贝的元素分配所需要的内存,所以临时变量之中含有vec中size()个元素,没有多余容量
    然后对这个临时变量调用swap,临时变量变成原vec(有多余容量),vec变成原临时变量(无多余容量)
    语句末尾swap之后的临时变量(有多余容量)被析构,从而释放了原vec中多余的容量,而现vec中无多余容量

    同样技巧对string同样适用:

    string str;
    string(str).swap(str);

    注:swap之后,不仅两容器中的元素被交换,同时它们的迭代器、指针、引用全被交换

    条款18:避免使用 vector<bool>

    vector<bool>是个假容器,并不真的存储 bool,真正存储的是 bool 的紧凑表示,实际上每个 bool 仅占一个二进制bit位,而不是一个字节
    应该使用 bitset 替代

  • 相关阅读:
    如何获取antlr解析的错误消息?(完美)
    2021最新版保姆级Journal Citation Reports使用
    【 Linux系统 】Centos下Linux启动时默认内核设置机制
    留言板
    友链
    java enum简记
    java enum多路分发下浅识表驱动式编程
    c语言建立和调用dll
    scanf
    js学习1 —— 类型,值,变量
  • 原文地址:https://www.cnblogs.com/wwwjieo0/p/3443989.html
Copyright © 2011-2022 走看看