C++ STL — 第6章 STL容器(一)vector

6.1 容器的共通能力和共通操作

  所有容器提供的都是value语意而非reference语意。容器元素必须能够被拷贝。

  总体而言,所有元素形成一个次序。运用迭代器遍历,也是算法的基础。

 

  各项操作并非安全,调用者必须确保参数符合要求。违反可能导致未定义行为。通常STL自身不抛出异常。


  初始化:每个容器提供了一个默认构造函数、copy构造函数、析构函数。

  容器类别的共通函数:

  C c;  不含任何元素的空容器

  C c(c1);   产生一个同型容器

  C c(beg, end);   复制区间元素,作为容器初值

  c.~C();   删除所有元素,释放内存

  c.size();  返回容器元素数量

  c.empty();  若容器为空返回true

  c.max_size();  返回容器内元素最大可能数量

  c1 == c2 ;   

  c1 != c2 ;   >  <  >=  <=

  c1 = c2;  将c2的所有元素赋值给c1

  c1.swap(c2);  交换c1和c2的数据

  swap(c1, c2);  同上,全局函数

  c.begin();   返回指向第一个元素迭代器

  c.end();  返回指向最后元素的下个位置的迭代器

  c.rbegin();  返回指向逆向遍历时候的第一个元素的逆向迭代器

  c.rend();  返回指向逆向遍历时候的最后元素的下个位置的逆向迭代器

  c.insert(pos, elem);  将elem的一份副本插入pos处,返回值和pos意义并不同

  c.erase(beg, end);  移除区间内所有元素

  c.clear();   移除所有元素

  c.get_allocator();  返回容器的内存模型


  以另一个容器的元素为初值完成初始化:

  list<int> l;

  vector<float> c(l.begin(), l.end());


  以某个数组元素为初始初始化:

  int a[] = { 2, 3, 17, 33, 45, 77 };

  set<int> c(a, a + sizeof(a)/sizeof(*a));


  标准输入完成初始化:

  deque<int> c((istream_iterator<int>(cin)),(istream_iterator<int>()));  //括号不能少,否则视为c为一个函数声明



6.2 vector : 动态数组

  #include <vector>

  具备assignable 和 copyable两个性质

  namespace std {

template <class T, class Allocator = allocator<T> >

class vector;  

  }

  //第二个参数一般省略,缺省是C++ STL提供的allocator分配器


  vector是有序群集,支持随机存取,随机存取迭代器,任何STL算法都适用。

  末端附加和删除元素时候,性能好。前端或中间插入和删除元素性能不好。因为要移动操作点之后的所有元素,这是很多 = 赋值操作符。

  capacity(); 返回vector实际能容纳的元素数量,如果超越这个数量vector就会重新配置内部存储器。

  一旦内存重新配置,和vector元素有关的所有reference、pointers、iterator都会失效,内存重新配置很耗时间。

  可以使用reserve()函数保留适当容量,只能增不能减,避免总是重新配置内存,避免iterator失效。 vector<int> v;   v.reserve(80);  分配了80个元素的v

  还可以在构造期间分配大小:  vector<int> v(100);  //v 起始大小100个元素


  构造和析构函数:

  vector<Elem> c;

  vector<Elem> c1(c2);

  vector<Elem> c(n);

  vector<Elem> c(n, elem);

  vector<Elem> c(beg, end);

  c.~vector<Elem>();


  非变动性操作:

  c.size();

  c.empty();

  c.max_size();

  capacity();

  reserve(n);

  c1 ==  c2; !=  <  >  <=   >=


  赋值:

  c1 = c2;

  c.assign(n, elem);

  c.assign(beg, end);

  c1.swap(c2);

  swap(c1, c2);


  元素存取:index 从0到size()-1; 对于non-const vector返回元素的reference;程序员自己检查范围例如是否为空;

  c.at(idx);  //out_of_range 异常

  c[idx];  不进行范围检查

  c.front();

  c.back();


  迭代器相关:其实就是个指针,vector内部结构是数组

  c.begin();  //随机存取迭代器

  c.end();

  c.rbegin();  //逆向迭代器

  c.rend();


  迭代器失效情况:较小的索引位置插入或移除元素;容量变化重新引起内存分配

  插入和移除元素使作用点之后的元素迭代器失效,甚至引发内存重新分配届时所有迭代器失效;


  移除插入相关操作:

  c.insert(pos, elem);  //返回新元素位置

  c.insert(pos, n, elem);  //无返回值

  c.insert(pos, beg, end);  //无返回值

  c.push_back(elem); 

  c.pop_back();

  c.erase(pos); //返回下一个元素的位置

  c.erase(beg, end);  //返回下一个元素的位置

  c.resize(num);  将元素数量改为num,如果size()增大了,多出新元素需要默认构造函数完成

  c.resize(num, elem);

  c.clear();  容器清空


  vector<Elem> c;

  c.erase(remove(c.begin(), c.end(), val), c.end());  //将所有其值为val的元素移除 

#include <algorithm>
#include <vector>
#include <iostream>
#include "print.cpp"
 
using namespace std;
 
int main()
{
    int a[] = {3, 4, 5, 3, 7, 9, 3, 4};
    vector<int> v(a, a+sizeof(a)/sizeof(*a));
    v.erase(remove(v.begin(), v.end(), 3), v.end());
 
    print_elements(v, "after erase: "); //4 5 7 9 4
    return 0;
}

若想移除与某值相等的第一个元素:

#include <algorithm>
#include <vector>
#include <iostream>
#include "print.cpp"
 
using namespace std;
 
int main()
{
    int a[] = {3, 4, 5, 3, 7, 9, 3, 4};
    vector<int> v(a, a+sizeof(a)/sizeof(*a));
    vector<int>::iterator pos = find(v.begin(), v.end(), 3);
    if(pos != v.end())
    {
        v.erase(pos);
    }
    print_elements(v, "after erase: "); //4 5 3 7 9 3 4
    return 0;
}

将vector当作一般array使用:

&v[i] = &v[0] + i;

vector<char> v;

v.resize(40);

strcpy(&v[0], "hello, world");

printf("%s\n", &v[0]);  //printf("%s\n", v.begin()); is error


异常处理:

下标操作的安全版本:at()

push_back()安插元素时候发生异常,插入不起作用

若元素拷贝不抛出异常,insert要么成功要么不生效

pop_back()不抛异常

若拷贝操作不抛异常,erase()和clear()不抛异常

swap()不抛异常

若拷贝操作绝对不抛异常,那么所有操作要么成功要么不起作用。

析构函数不抛异常


一个例子总结vector:

#include <algorithm>
#include <vector>
#include <iostream>
#include "print.cpp"
#include <string>
 
using namespace std;
 
int main()
{
    vector<string> s;
    s.reserve(5);
 
    s.push_back("Hello, ");
    s.push_back("how ");
    s.push_back("are ");
    s.push_back("you ");
    s.push_back("?");
 
    print_elements(s, "init: ");  //init: Hello,  how  are  you  ?
 
    cout << "max_size(): " << s.max_size() << endl;  //1073741823
    cout << "size(): " << s.size() << endl;  //5
    cout << "capacity(): " << s.capacity() << endl; //5
 
    swap(s[1], s[3]);
    s.insert(find(s.begin(), s.end(), "?"), "always");
 
    s.back() = "!";
 
    print_elements(s, "after: ");  //after: Hello,  you  are  how  always !
 
    cout << "max_size(): " << s.max_size() << endl;  //1073741823
    cout << "size(): " << s.size() << endl;   //6
    cout << "capacity(): " << s.capacity() << endl;  //10
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值