C++ primer 第九章复习 - 1(下)

简介: C++ primer 第九章复习 - 1

使用 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(); //要求归还内存,只是请求,不保证退还


相关文章
|
7月前
|
编译器 C++
c++primer plus 6 读书笔记 第十章 对象和类
c++primer plus 6 读书笔记 第十章 对象和类
|
7月前
|
编译器 数据安全/隐私保护 C++
c++primer plus 6 读书笔记 第十三章 类继承
c++primer plus 6 读书笔记 第十三章 类继承
|
7月前
|
C++
C++ Primer Plus (第6版)中文版 (使用XMind整理)
C++ Primer Plus (第6版)中文版 (使用XMind整理)
C++ Primer Plus (第6版)中文版 (使用XMind整理)
|
7月前
|
C++
c++primer plus 6 读书笔记 第十四章 C++中的代码重用
c++primer plus 6 读书笔记 第十四章 C++中的代码重用
|
7月前
|
C++
c++primer plus 6 读书笔记 第十一章 使用类
c++primer plus 6 读书笔记 第十一章 使用类
|
7月前
|
编译器 C++
c++primer plus 6 读书笔记 第八章 函数探幽0
c++primer plus 6 读书笔记 第八章 函数探幽0
|
7月前
|
编译器 vr&ar C++
c++primer plus 6 读书笔记 第七章 函数--C++的编程模块
c++primer plus 6 读书笔记 第七章 函数--C++的编程模块
|
7月前
|
SQL 人工智能 算法
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
技术心得记录:模板函数函数模板FunctionTemplate(C++Primer
|
7月前
|
程序员 C++
c++primer plus 6 读书笔记 第十二章 类和动态内存分配
c++primer plus 6 读书笔记 第十二章 类和动态内存分配
|
7月前
|
存储 IDE 编译器
c++primer plus 6 读书笔记 第九章 内存模型和名称空间
c++primer plus 6 读书笔记 第九章 内存模型和名称空间