c++11学习笔记(8)

(1)新标准引入了3个新成员,emplace_front, emplace和emplace_back,这些操作构造而不是拷贝元素,这些操作分别对应push_front,push,push_back,允许我们将元素放置在容器头部,一个指定位置之前,容器尾部。
(2)当调用push或insert成员函数时,我们将元素类型的对象传递给它们,这些对象被拷贝到容器中。而当我们调用一个emplace成员函数时,则是将参数传递给元素类型的构造函数。emplace成员使用这些参数在容器管理的内存空间中直接构造元素。
(3)假定c保存sales_data

c.emplace_back("45224", 25, 15.99);
c.push_back("45224", 25, 15.99);
上面这个是错误的
c.push_back(sales_data("45224", 25, 15.99));

其中正确的两个调用都会创建新的sales_data对象,在调用emplace_back的时候,会在容器管理的内存空间中直接创建对象。而调用push_back则会创建一个局部临时对象,并将其压入容器中。
(4)包括array在内的每个顺序容器都有一个front成员,而除了forward_list之外的所有顺序容器都有一个back成员函数。这两个操作分别返回首元素和尾元素的引用。

复制代码
if(!c.empty())
{
  auto val = *c.begin(), val2 = c.front;
  auto last = c. end();
  auto val3 = *(--last);
  auto val4 = c back();
}
复制代码

此程序用两种不同的方式来获取c中的首元素和尾元素的引用,直接的方法是调用front和back,而间接的方法是通过解引用begin返回的迭代器来过的首元素的引用,以及通过递减然后解引用end返回的迭代器来获得尾元素的引用。
(5)在容器中访问元素的成员函数(front/back/at)返回的都是引用,如果容器是一个const对象,则返回值是const的信用。如果容器不是const的,则返回值是普通引用,我们可以用来改变元素的值。

复制代码
if(!c.empty())
{
  c.front() = 42; 
  auto &v = c. back();
  v = 1024;//引用可以改变
  auto v2 = c. back();
  v2 = 0//没有改变c中的元素
}
复制代码

(6)下标运算符接受一个下标参数,返回容器中该位置的元素的引用,给定下标必须在范围内。如果我们希望确保下标是合法的,可以使用at函数,at函数类似下标运算符,但如果下标越界,at会抛出一个out_of_range异常。

vector<string> svec;
cout << svec[0];
cout << svec. at(0);

(7)非array容器有多种删除元素的方式。
pop_front和pop_back成员函数分别删除首元素和尾元素。和vector和string不支持push_front一样,这些类型也不支持pop_front。类似的,forward_list不支持pop_back。和元素访问成员函数类似,不能对一个空容器执行弹出操作。
(8)这些弹出操作返回void,如果你需要弹出的元素值,就必须在执行弹出之前保存他。
(9)成员函数erase从容器中指定位置删除元素,我们可以删除一个由迭代器指定的单个元素,也可以删除由一对迭代器指定的范围内的所有元素。两种形式的erase都返回指向删除的最后一个元素之后位置的迭代器。
例如,下面的循环删除一个list中的所有奇数元素。

复制代码
list<int> lst = {0, 1, 2, 3, 4, 5, 6, 7};
auto it = lst. begin();
while(it != lst.end())
  if(*it % 2)//如果元素是奇数
    it = lst. erase(it);
  else
    ++it;
复制代码

(10)可以接受一对迭代器删除多个元素

slist. clear();
slist. erase(slist.begin(), slist.end());

(11)当添加或删除一个元素时,删除或添加元素之前的那个元素的后继会发生改变。为了添加或删除一个元素我们需要访问其前驱,以便改变前驱的链接。但是,forward_list是单向链表,没有简单的方法过去一个元素的前驱。出于这个原因,在一个forward_list中添加或删除元素的操作是通过改变给定元素之后的元素来完成的。这样我们总是可以访问到被添加或删除操作所影响的元素。
(12)由于这些操作和其他容器上的操作实现方式不同,forward_list并未定义insert/emplace/erase。而且定义了名为insert_after/emplace_after/erase_after的操作。为了删除elem3,应该用指向elem2的迭代器调用erase_after。为了支持这些操作,forward_list也定义了before_begin,它返回一个首前迭代器。这个迭代器允许我们在链表首元素之前并不存在的元素之后添加或删除元素,也就是在链表首元素之前添加删除元素。
(13)

复制代码
forward_list<int> flst = {0, 1, 2, 3, 4, 5, 6};
auto prev = flst. before_begin();
auto curr = flst. begin();
while(curr != flst.end())
{
  if(*curr % 2)如果元素是奇数
    curr = flst. erase_after(prev);
  else
    prev = curr;
    ++curr;移动迭代器curr,指向下一个元素,prev指向curr之前的元素
}
复制代码

(13)可以使用resize来增大或缩小容器,如果当前大小大于所要求的大小,容器后部的元素会被删除,如果当前大小小于所要求的,会将新元素添加到容器后部。

list<int> ilist(10, 42);10和int,每个值都是42
ilist. resize(15);将5个0放在ilist的末尾
ilist. resize(25, -1);将10个-1添加到末尾
ilist. resize(5);从ilist末尾删除20个元素

 

posted @   花与不易  阅读(75)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示