美文网首页C++步步为营
C++---CHAPTER 9: CONTAINER

C++---CHAPTER 9: CONTAINER

作者: 世界上的一道风 | 来源:发表于2019-07-24 08:31 被阅读0次
    • 顺序容器
    vector 尾部之外的位置插入或删除元素可能很慢
    deque 头尾位置插入、删除速度很快
    list 任何位置插入、删除速度很快
    forward_list 只支持单向顺序访问,任何位置插入、删除都很快。
    array 固定大小数组。不能添加删除元素
    string 随机访问快、尾部插入删除很快。
    • 容器操作
    类型别名
    iterator 此容器类型的迭代器类型
    const_iterator 读取元素,不能修改元素的迭代器类型
    size_type 无符号类型,保存此容器类型的最大可能容器的大小
    difference_type 带符号整数类型,两个迭代器之间的距离
    value_type 元素类型
    reference 元素的左值类型;与value_type&含义相同
    const_reference 元素的const左值类型(vonst vlue_type&)
    构造函数
    C c; 默认构造函数,构造空容器
    C c1(c2); 构造c2的拷贝到c1
    C c(b,e); 构造c,将接待器b和e范围的元素拷贝到c(不支持array)
    C c{a, b, c,...} 列表初始化c
    赋值与swap
    C1 = c2
    C1 = {a, b, c,...}
    a.swap(b);swap(a,b) 交换a与b的元素
    大小
    c.size() c中元素的数目(不支持forward_list)
    c.max_size() c可保存的最大元素数目
    c.empty()
    添加或删除元素 在不同容器中,操作的接口不同
    c.insert(args) 将args中的元素拷贝到c
    c.emplace(inits) 使用inits构造c中的一个元素
    c.erase(args) 删除args指定的元素
    c.clear() 删除c中的所有元素,返回void
    关系运算符 所有容器都支持:如==、!=
    获取迭代器
    c.cbegin(),c.cend() 返回const_iterator
    reverse_iterator 逆序寻址的迭代器

    容器定义和初始化

    C seq(n);       // seq包含n个元素,都被值初始化
    C seq(n, t);  // seq包含n个值为t的元素
    list<string> authors = {"Milton", "Austen"}; //列表初始化
    
    • notes: 1. 将一个容器初始化为另一个容器的拷贝时,两个容器的容器类型和元素类型都必须相同。
    1. 顺序容器的构造函数才接受大小参数,关联容器并不支持。
    • 标准库 array
      使用array必须指定元素类型和大小:
    array<int, 42> // 类型为:保存42个int的数组
     array<int>:: size_type j;  //错误
    

    不能对内置数组类型进行拷贝,但是array类型是可以的:

    array<int ,10> digits = {0,1,2,3,4,5,6,7,8,9};
    array<int, 10> copy = digits; // right
    

    容器赋值运算

    赋值和swap

    array<int, 10> a1 = {...};
    array<int 10> a2 = {0}; //所有元素均为 0
    a2 = {0}; //错误,不能将一个花括号列表赋予数组
    
    // 通常swap比从c2向c1拷贝元素要快
    swap(c1,c2);
    c1.swap(c2);  
    
    seq.assign(b, e); // 将seq中的元素替换为迭代器b和e所表示的范围的元素,迭代器b、e不能指向seq中的元素
    seq.assign(il); // 将seq中的元素替换为初始化列表il中的元素
    seq.assign(n,t); // 将seq中的元素替换为n个值为t的元素
    
    • 警告:赋值相关运算会导致指向左边容器内部的迭代器、引用和指针失效。而swap操作将容器内容交换不会导致指向容器的迭代器、引用和指针失效(array和string除外)。

    • 顺序容器的assign
      允许我们从一个不同但相容的类型赋值,或者从容器的一个子序列赋值。assign操作用参数所指定的元素(的拷贝)替换左边容器中的所有元素。

    list<string> names;
    vector<const char*> oldstyle;
    names = oldstyle; //错误,容器类型不匹配
    names.assign(oldstyle.cbegin(), oldstyle.cend()); //正确 可以将const char* 转换为string
    

    向顺序容器添加元素

    c.push_back(t) , c.emplace_back(args) c的尾部创建一个值为t或由args创建的元素。
    c.insert(p,t) , c.emplace(p,args) 在迭代器p指向的元素之前创建一个值为p或由args创建的元素。
    c.insert(p, n , t) 在迭代器p指向的元素之前插入n个值为t的元素。返回新添加的第一个元素的迭代器,若n为0,返回p
    c.insert(p, b, e) 将迭代器b、e指定的范围内的元素插入到迭代器p指向的元素之前。b、e不能指向c中的元素。 返回新添加的第一个元素的迭代器,若n为0,返回p
    c.insert(p , il) il是一个花括号保卫的元素值列表,将这些值插入到p指向的元素之前。 返回新添加的第一个元素的迭代器,若n为0,返回p
    • insert的返回值
      下面的例子,iter每次都指向新加入元素的位置:
    list<string> lst;
    auto iter = lst.begin();
    while(cin>>word)
      iter = lst.insert(iter, word); //等价于调用 push_front
    
    • 使用emplace操作
      假设c里保存的是Sales_data成员:
    c.emplace_back("970", 25, 15.99);
    c.push_back("970", 25, 15.99); //错误,没有接受三个参数的push_back
    c.push_back(Sales_data("970", 25, 15.99));
    

    在调用emplace_back时,会在容器管理的内存空间中直接创建对象,而调用push_back则会创建一个局部临时对象,并压入容器中。

    在顺序容器汇总访问元素

    • 容器中没有元素,访问操作是未定义的。
    • 包括array在内每个顺序容器都有一个front成员函数,除去forward_list之外的所有顺序容器都有back成员函数。
      vector<int> c={1,2,3,4,5,6};
      if (!c.empty()){
        // val和val2是c中第一个元素值的拷贝
        auto val = *c.begin(), val2 = c.front();
        // val3和val4是c中最后一个元素值的拷贝
        auto last =c.end();
        auto val3 =*(--last); // 不能递减forward_list迭代器
        auto val4 = c.back();
        cout << val << " " << endl;
        cout << val2 << " " << endl;
        cout << val3 << " " << endl;
        cout << val4 << " " << endl;
      }
    
    • 访问成员函数返回的是引用:frontbackat、下标都是返回引用,如果容器是一个const对象,返回值是const的引用。
      vector<int> c={1,2,3,4,5,6};
      if (!c.empty()){
        c.front() = 42;
        auto &v = c.back(); // v是c.back()的一个引用
        v = 1024;
        cout << c.back() << endl;
        auto v2 = c.back(); // v2不是一个引用,它是c.back()的一个拷贝
        v2 = 0;
        cout <<c.back();
      }
    
    
    1024
    1024
    
    • 下标操作和安全的随机访问:at在下标越界的情况下,会抛出一个out_of_range的异常。
    vector<string> svec;
    cout << svec[0]; // 运行时错误
    cout << svec.at(0); //抛出一个异常
    

    顺序容器的删除操作

    • 注意:删除deque中除首尾位置之外的任何元素都会是所有迭代器、引用、指针失效。指向vectorstring中删除点之后的迭代器、引用、指针失效。
    c.pop_back() 删除c中的尾元素。c为空,函数行为未定义。函数返回void
    c.pop_front() 删除c中的首元素。c为空,函数行为未定义。函数返回void
    c.erase(p) 删除迭代器p指定的元素,返回一个指向被删除元素之后元素的迭代器,若p是尾后迭代器,则函数行为未定义
    c.erase(b, e) 将迭代器b、e指定的范围内的元素删除。若e是尾后迭代器,则函数返回尾后迭代器
    c.clear() 删除所有元素,返回void

    改变容器的大小

    resize增大或缩小容器,array不支持。如果当前大小大于所要求的大小,容器后部的元素被删除;如果当前大小小于新大小,新元素会添加:

    list<int> ilist(10, 42); // 10个int:每个值为42
    ilist.resize(15); // 将5个值为0的元素添加到ilist尾部
    ilist.resize(25, -1); //  将10个值为-1的元素添加到ilist末尾
    ilist.resize(5); // 从ilist末尾删除20个元素
    

    相关文章

      网友评论

        本文标题:C++---CHAPTER 9: CONTAINER

        本文链接:https://www.haomeiwen.com/subject/wzctrctx.html