【人迹C++primer】26、顺序容器操作

【足迹C++primer】26、顺序容器操作

顺序容器操作

 向顺序容器添加元素

forward_list //有自己专有版本的insert和emplace;
forward_list    //不支持push_back和emplace_back
vector, string  //不支持push_front和emplace_front

c.push_back(t), c.emplace_back(args)  //在c的尾部创建一个值为t的或者由args创建的元素,返回void
c.push_front(t), c.emplace_back(args)   //同上,吧尾部改为头部

c.insert(p,t), c.emplace(p,args)    //在迭代器p的前面创建一个t或由args生产一个值插入,返回指向新添加元素的迭代器
c.insert(p, n, t)   //在迭代器p指向的元素之前插入n个t值,返回指向新添加的第一个值的迭代器。
c.insert(p, b, e)   //吧迭代器b,e之间的元素插入到p之前,返回指向新添加的第一个元素
c.insert(p, il)     //il是一个花括号包围的元素值列表。同上

使用push_back

//从标准输入读取数据,将每个单词放到容器末尾
string word;
while(cin>>word)
    container.push_back(word);

由于string是一个字符容器,我们可以用push_back在string末尾添加字符:
void pluralize(size_t cnt, string &word)
{
    if(cnt > 1)
        word.push_back('s');    //等价word +='s'
}

使用push_front

这个操作是吧元素插入到容器头部,
list<int> ilist;
for(size_t ix=0 ; ix != 4 ; ++ix)
{
    ilist.push_front(ix);
}

向容器总的特定位置添加元素

insert提供更加一般的添加功能,随机插入。
有些容器不支持push_front,但它们对于insert操作并无类似的限制
vector<string> svec;
list<string> slist;

//等价于调用slist.push_front("Hello!");
slist.insert(slist.begin(), "Hello!");
svec.insert(svec.begin(), "Hello!");    //速度回比较慢

使用emplace操作

//在c的末尾构造一个Sales_data对象
//使用三个参数的Sales_data构造函数
c.emplace_back("978-0590353403", 25, 15.99);
//错误:没有接受三个参数的push_back版本
c.push_back("978-0590353403", 25, 15.99);
//正确:创建一个临时的Sales_data对象传递给push_back
c.push_back(Sales_data("978-0590353403", 25, 15.99));

emplace函数在容器中直接构造元素。传递给emplace函数的参数必须与元素类型的构造函数相匹配。

访问元素

//在解引用一个迭代器或调用front或front之前检查是否有元素
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();     //forward_list不支持
}

这里还有两种访问方式
at和下标操作
但是只适用于string, vector, deque, array
c[n]    //返回c中下标为n的元素引用

c.at(n)     //返回c中下标为n的元素引用

访问成员函数返回的是引用,下标操作和安全的随机访问

vector下标是从0开始的,但是如果vector为空的话,那么
vector<string> svec;    //空vector
cout<<svec[0];          //运行错误,vector是空的
cout<<svec.at(0);       //抛出一个out_of_range异常

删除元素

c.pop_back()    //删除c中尾元素
c.pop_front()   //删除c中首元素
c.erase(p)      //删除迭代器p指向的元素
c.erase(b, e)   //删除迭代器b和e之间的元素
c.clear()       //删除c中的所有元素

pop_front和pop_back成员函数

而且这些操作的返回值是void,所以在弹出之前要保存好这个值
while(!ilist.empty())
{
    process(ilist.front());     //对ilist的首元素进行一些处理
    ilist.pop_front();          //完成处理后删除元素
}

从容器内部删除一个元素

循环删除一个list中的所有奇数
list<int> lst={0,1,2,3,4,5,6,7,8,9};
auto it=lst.begin();
while(it != lst.end())
    if(*it%2)               //若为奇数
        it=lst.erase(it);   //删除此元素
    else
        ++it;

特殊的forward_list操作

forward_list<int> flst={0,1,2,3,4,5,6,7,8,9};
auto prev=flst.before_begin();      //表示flst的“首前元素”
auto curr=flst.begin();             //表示flst总的第一个元素
while(curr != flst.end())
{
    if(*curr%2)
    {
        curr=flst.erase_after(prev);    //删除并移动curr位置
    }
    else
    {
        prev=curr;
        ++curr;
    }
}

该表容器的大小

使用resize来增大或缩小容器,和往常一样array不支持resize。
list<int> ilist(10, 42);    //10个int:每个的值都是42
ilist.resize(15);           //将5个值为0的元素添加到ilist的末尾
ilist.resize(25, -1);       //将10个值为-1的值加到末尾
ilist.resize(5);            //从末尾删除20个元素

好的我们要知道对容器的操作会改变迭代器的有效性!!!
看程序!!!
//傻瓜循环,删除偶数元素,复制每个奇数元素
vector<int> vi={0,1,2,3,4,5,6,7,8,9};
auto iter=vi.begin();       //调用begin而不是cbegin,因为我们要改变vi
while(iter != vi.end())
{
    if(*iter%2)
    {
        iter=vi.insert(iter, *iter);    //复制当前元素,插在前面,返回指向新加的元素的
        //迭代器
        iter+=2;
    }
    else
    {
        iter=vi.erase(iter);    //删除偶数元素
        //不应该向前移动迭代器,iter指向我们删除之后的元素
    }
}

PS:不干了,尼玛这太长了,先让我好好消化一下,而且马上就考试了,忙死啦!!!!【人迹C++primer】26、顺序容器操作【人迹C++primer】26、顺序容器操作我要坚持不下了!!!