使用 emplace 操作
构造元素而不是拷贝元素
访问元素
at 和下标操作只适用于 string ,vector ,deque 和 array
std::list<int> l1; //调用 front 或 back 前需检查是否有元素 if (!l1.empty()){ //val 和 val2 是第一个元素值的拷贝 auto val = *l1.begin(), val2 = l1.front(); //val3 val4 是最后一个元素值的拷贝 auto last = l1.end(); auto val3 = *(--last); //forward_list 迭代器不支持 auto val4 = l1.back(); //forward_list 不支持 }
访问成员函数返回的是引用
使用 auto 变量保存这些函数返回值,若希望改变元素值,需定义为引用类型
if (!l1.empty()){ l1.front() =42; auto& v = c.back(); //改变末尾元素值 v =1024; }
删除元素
pop_front 和 pop_back 成员函数 while (!l1.empty()){ process(l1.front()); //对首元素进行一些处理 l1.pop_front(); //处理后,删除首元素 }
从容器内部删除元素
//删除list中所有奇数元素 std::list<int> l2 = { 0, 1, 2, 3, 4, 5, 6 }; auto it = l2.begin(); while (it != l2.end()){ if (*it % 2){ //若元素为奇数 it = l2.erase(it); //删除此元素,返回被删元素之后位置的迭代器 } else { ++it; } } //删除两个迭代器范围内的元素 //返回指向最后一个被删元素之后位置的迭代器 auto it3 = l2.erase(it2, it3); //调用后 it2 == it3 //删除容器所有元素,等价调用 l2.clear(); l2.erase(l2.begin(), l2.end());
特殊的 forward_list 操作
简单的描述,就是因为删除一个元素要改变其前一个元素的后继,但是单向链表无法访问其前一个元素。所以,删除某位置元素应当调用 erase_after 该位置的的前一个位置,添加一个则调用该位置的前一个位置 before_begin (首前迭代器)
std::forward_list<int> flist = { 0, 1, 2, 3, 4, 5, 6 }; auto prev = flist.before_begin(); //表示flist的首前位置 auto curr = flist.begin(); //表示flist第一个元素 while (curr != flist.end()){ if (*curr % 2){ curr = flist.emplace_after(prev); //删除并移动curr } else { prev = curr; //移动迭代器curr,指向下一个元素 ++curr; } }
改变容器大小
resize :用元素填充容器
std::list<int> list(10, 42); //10个int:每个值都是42 list.resize(15); //将5个值为0的元素添加到末尾 list.resize(25,-1); //将10个值为 -1 的元素插入末尾 list.resize(5); //从末尾删除20个元素
容器操作可能使迭代器失效
编写改变容器的循环程序
此程序删除容器的偶数元素,并复制奇数元素,在调用 insert 和 earse后都更新迭代器,因为两者都会使迭代器失效
std::vector<int> vi= { 0, 1, 2, 3, 4, 5 }; auto Iter =vi.begin(); while (Iter !=vi.end()){ if (*Iter % 2){ Iter =vi.insert(Iter, *Iter); //复制当前元素 Iter +=2; //向前移动迭代器,跳过当前元素和复制元素 } else { Iter =vi.erase(Iter); //删除偶数元素 } }
不要缓存 end 符合的迭代器
像上述代码一致,应重新调用 end 迭代器
9.4 vector 是如何增长的
若没有空间容纳新元素,就必须分配新的空间来保存已有元素和新元素。如果每添加一个元素,vector就执行一次内存分配和释放,性能太差
reserve 并不改变容器中元素的数量,它仅影响vector 预分配多大的内存空间
std::vector<int> ivec; std::cout << ivec.size() << std::endl; //0 std::cout << ivec.capacity() << std::endl; //依赖具体实现 for (int i =0; i <=24; ++i){ ivec.push_back(i); } std::cout << ivec.size() << std::endl; //24 std::cout << ivec.capacity() << std::endl; //大于或等于24 ivec.reserve(50); //将capacity设置为50 ivec.shrink_to_fit(); //要求归还内存,只是请求,不保证退还
一个元素,vector就执行一次内存分配和释放,性能太差
reserve 并不改变容器中元素的数量,它仅影响vector 预分配多大的内存空间
std::vector<int> ivec; std::cout << ivec.size() << std::endl; //0 std::cout << ivec.capacity() << std::endl; //依赖具体实现 for (int i =0; i <=24; ++i){ ivec.push_back(i); } std::cout << ivec.size() << std::endl; //24 std::cout << ivec.capacity() << std::endl; //大于或等于24 ivec.reserve(50); //将capacity设置为50 ivec.shrink_to_fit(); //要求归还内存,只是请求,不保证退还