• 顺序容器操作


    向顺序容器添加元素

    除了 array 之外,所有的标准库容器都提供了灵活的内存管理,在运行时可以动态增加或删除元素来改变容器的大小。

    使用 push_back

    除了 array 和 forward_list之外,每个顺序容器(包含string类型)都支持 push_back。

    void pluralize(size_t cnt,string &word)
    {
    	if(cnt > 1)
    		word.push_back('s');	//等价于 word += 's'
    }
    

    使用 push_front

    除了 push_backlistforward_listdeque 容器还支持 push_front 的类似操作,该操作将元素插入到容器头部。

    list<int> ilist;
    for(size_t ix=0;ix!=4;++ix)
    	ilist.push_front(ix);
    

    在容器中的特定位置添加元素

    insert 成员提供了更一般的添加功能,它允许在容器中任意位置插入0个或多个元素。

    vectordequeliststring 都支持 insert

    forward_list 提供了特殊版本的 insert成员。

    insert 函数接受一个迭代器作为其第一个参数,迭代器指出了在容器中什么位置放置新元素。它可以指向容器的任何位置,包括容器尾部之后的下一个位置。

    insert 函数将元素插入到迭代器所指定的位置之前。

    slit.insert(iter,"hello");	//将hello插入到iter之前的位置
    

    由于某些容器不支持 push_front 操作,但它们对于 insert 操作并无类似的限制,因此可以将元素插入到容器的开始位置,而不必担心容器是否支持 push_front

    vector<string> svec;
    list<string> slist;
    
    // 等价于调用slist.push_front("hello")
    slist.insert(slist.begin(),"hello");
    //vector 不支持push_front,但是可以在begin()之前加入元素
    svec.insert(svec.begin(),"hello");
    

    把元素插入到 vectordequestring 中的任何位置都是合法的,然而,这样做可能很耗时。

    插入范围内元素

    insert 函数除了接受一个迭代器参数外,还可以接受一个元素数目和一个值,它将指定数量的元素添加到指定位置之前,这些元素都按照给定的值初始化。

    svec.insert(svec.end(),10,"Anna");
    

    这行代码将10个元素插入到 svec 的末尾,并将所有的元素都初始化 "Anna"

    接受一个迭代器或一个初始化列表的insert版本将给定范围中的元素插入到指定的位置之前:

    vector<string> v = {"quasi","simba","frollo","scar"};
    
    //将v的最后两个元素添加到slist的开始位置
    slist.insert(slist.begin(),v.edn()-2,v.end());
    slist.insert(slist.end(),{"these","words","will","go","at","the","end"});
    
    //运行时错误,迭代器表示要拷贝的范围,不能指向与目的位置相同的容器
    slist.insert(slist.begin(),slist.begin(),slist.end());
    

    如果传递给 insert 一对迭代器,它们不能指向添加元素的目标容器。

    如果范围为空,不插入任何元素,insert 操作会将第一个参数返回。

    使用 insert 的返回值

    通过使用 insert 的返回值,可以在容器中一个特定位置反复插入元素:

    list<string> lst;
    auto iter = lst.begin();	//将iter初始化为lst.begin()
    while(cin >> word)
    	iter = lst.insert(iter,word); //等价于调用push_front
    

    使用 emplace 操作

    emplace_frontemplaceemplace_back 这些操作不是构造而是拷贝元素,这些操作分别对应 push_frontinsertpush_back,允许将元素放置在容器头部,一个指定位置之前或容器尾部。

    调用 pushinsert 函数是将元素类型的对象传递给它们,这些对象被拷贝到容器中。

    调用 emplace 时是将参数传递给元素类型的构造函数,emplace 成员使用这些参数在容器管理的内存中直接构造元素。

    //在c的末尾构造一个 Sales_data 对象
    
    //使用三参数的 Sales_data 构造函数
    c.emplace_back("9-999-999-9",25,12,99);
    
    //没有接受三个参数的push_back版本
    c.push_back("9-999-999-9",25,12,99);
    
    //创建一个临时的 Sales_data 对象,并将其传递给push_back
    c.push_back(Sales_data("9-999-999-9",25,12,99));
    

    emplace 函数的参数根据元素类型而变化,参数必须与元素类型的构造函数相匹配。

    c.emplace_back(); 	//使用Sales_data的默认构造函数
    c.emplace(iter,"9-999-999-9");	//使用Sales_data(string)的构造函数
    c.emplace_front("9-999-999-9",25,12,99);	//使用接受一个ISBN,COUNT,PRICE版本的构造函数
    

    访问元素

    包括 array 在内的每个顺序容器都有一个 front 成员,而除 forward_list 之外的所有容器都有一个 back 成员函数,这两个操作分别返回首元素和尾元素的引用。

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

    迭代器 end 指向的是容器尾元素之后的元素,为了获取尾元素,必须首先递减此迭代器。

    在调用 frontback (解引用begin 或 end 返回的迭代器)之前,要确保 c 非空,如果容器为空,if 操作的行为将是未定义的。

    访问成员函数返回的是引用

    在容器中访问元素的成员函数即 front、back、下标和at返回的都是引用。

    如果容器是一个 const对象,则返回值是const的引用。如果容器不是const的,则返回值是普通的引用,可以用来改变元素的值。

    if (!c.empty())
    {
        c.front() = 42;		//将42赋值给c中的第一个元素
        auto &v = c.back();	//获取指向最后一个元素的引用
        v = 1024;	//改变c中的元素
        auto v2 = c.back();	//v2不是一个引用,它是c.back() 的一个拷贝
        v2 = 0;		//未改变c中的元素
    }
    

    下标操作和安全的随机访问

    提供快速随机访问的容器 stringvectordequearray 也都提供下标运算符。

    使用越界的下标是一种严重的错误,并且编译器并不检查这种错误。

    如果希望确保下标是合法的,可以使用 at 成员函数,使用 at 成员函数,如果下标越界,at 会抛出一个 out_of_range 异常。

    vector<string> svec;
    cout<<svec[0];		//运行时错误,svec中没有元素
    cout<<svec.at(0);	//抛出一个out_of_range异常
    

    删除元素

    array 容器也有多种删除方式。

    pop_front 和 pop_back 成员函数

    pop_frontpop_back 成员函数分别删除首元素和尾元素。

    vectorstring 不支持 push_front 一样,这些类型也不支持 pop_frontforward_list 不支持pop_back

    不能对一个空容器执行弹出操作。

    while(!ilist.empty())
    {
    	process(ilist.front());	//对ilist的首元素进行处理
    	ilist.pop_front();	//完成处理后删除首元素
    }
    

    从容器内部删除一个元素

    成员函数 erase 从容器中指定位置删除元素:

    • 可以删除由一个迭代器指定的单个元素。
    • 也可以删除由一对迭代器指定的范围内的所有元素。

    两种形式的 erase 都返回指向删除的(最后一个)元素之后位置的迭代器。

    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;
    }
    

    删除多个元素

    接受一对迭代器的 erase 版本允许删除一个范围内的元素:

    //删除两个迭代器表示的范围内的元素
    //返回指向最后一个被删除元素之后位置的迭代器
    elem1 = slist.erase(elem1,elem2);	//调用后,elem1 == elem2
    

    如果要删除一个容器中的所有元素:

    • 可以使用 密密麻麻扩扩扩军军,,,,,,clear。
    • 也可以用 begin 和 end 获取的迭代器作为参数调用erase。
    slist.clear();
    slist.erase(slist.begin(),slist.end());
    
  • 相关阅读:
    数据库之case when + group by 联合使用
    JAVA之JSON对象解析
    oracle导入表数据时遇到外键约束问题导致导入失败
    Oracle之会话阻塞
    cmd的操作命令导出导入.dmp文件
    性能优化理解
    JS原型与原型链的理解
    Promise实现原理
    Js运行机制Event Loop
    JS循环中断与异步for...in forEach map
  • 原文地址:https://www.cnblogs.com/xiaojianliu/p/12497187.html
Copyright © 2020-2023  润新知