与容器相关的函数与结构

  • 标准库的begin和end函数(只能用数组名做参数,不适用于在堆上申请的数组)

        为了让指针使用更简单、更安全,C++11引入俩个名为begin和end的函数,这俩个函数与容器中的俩个同名成员功能类似,不过数组毕竟不是类类型,因此这俩个函数不是成员函数,正确的使用形式是将数组作为他们的参数。这俩个函数定义在iterator头文件中,使用begin和end可以很容易地写出一个循环并处理数组中的元素。

int ia[] = { 0,1,2,3,4,5,6,7,8,9 };  //ia是一个含有10个整数的数组
int* pbeg = begin(ia);		//指向ia首元素的指针
int* pend = end(ia);		//指向arr尾元素的下一位置的指针
while (pbeg != pend)
{
	cout << *pbeg << endl;
	++pbeg;
}
  • 容器的cbegin和cend函数

        容器的begin和end返回的具体类型由对象是否是常量决定,如果对象是常量,begin和end返回const_iterator,如果对象不是常量,返回iterator,为了便于专门得到const_iterator类型的返回值,C++11引入了cbegin和cend,不论vector对象本身是否是常量,返回值都是const_iterator。

vector<int> v;
const vector<int> cv;
auto it1 = v.begin();		//it1的类型是vector<int>::iterator
auto it2 = cv.begin();		//it2的类型是vector<int>::const_iterator
auto it3 = v.cbegin();		//it3的类型是vector<int>::const_iterator
  • array和forward_list

          array和forward_list是新C++标准增加的类型,与内置数组相比,array是一种更安全、更容易使用的数组类型,与内置数组类似,array对象的大小是固定的,因此array不支持添加和删除元素以及改变容器大小的操作forward_list的设计目标是达到与最好的手写的单向链表数据结构相当的性能,因此forward_list没有size操作,因为保存或计算其大小就会比手写链表多出额外的开销,对其他容器而言,size保证是一个快速的常量时间的操作与内置数组一样,标准库array的大小也是类型的一部分,当定义一个array时,除了制定元素类型,还要制定容器大小。

array<int, 42>  //类型为保存42个int的数组
array<string, 10>  //类型为保存10个string的数组

       array不支持普通的容器的构造函数,array大小固定的特性也影响了它所定义的构造函数的行为,与其他容器不同,一个默认构造的array是非空的,它包含了与其大小一样多的元素,这些元素都被默认初始化,如果我们对array进行列表初始化,初始值的数目必须等于或者小于array的大小如果元素类型是一个类类型,那么该类必须有一个默认构造函数,以使值初始化能够进行,值得注意的是,虽然我们不能对内置数组类型进行拷贝或对象赋值操作,但array并无此限制

array<int, 10> digits = { 0,1,2,3,4,5,6,7,8,9 };
array<int, 10> copy = digits;  //正确 只要数组类型匹配即合法
  • 容器的非成员函数swap

swap操作交换俩个相同类型容器的内容,调用swap之后,俩个容器中的元素将会交换:

vector<string> svec1(10);
vector<string> svec2(24);
sve1.swap(svc2);

        除array外,交换俩个容器内容的操作保证会很快,因为时元素本身并未交换,swap只是交换了俩个容器的内部数据结构,除array外,swap不对任何元素进行拷贝、删除或插入操作,因此可以保证在常数时间内完成。元素不会被移动事实意味着,除string外,指向容器的迭代器、引用和指针在swap操作之后都不会失效,它们仍指向swap操作之前所指向的那些元素,但是在swap之后,这些元素已经属于不同的容器了, 例如假定iter在swap之前指向svec1[3]的string,那么在swap之后它指向svec2[3]的元素,与其他容器不同,对一个string调用swap会导致迭代器、引用和指针失效,这里是指string容器去调用,也就是 string s1; string s2; s1.swap(s2); 而不是其他string类型的容器,比如vector<string>。与其他容器不同,swap俩个array会真正交换他们的元素,因此交换俩个array所需的时间与array中元素的数目成正比,因此对于array,在swap操作之后,指针、引用和迭代器所绑定的元素保持不变,但元素值已经与另一个array中对应的元素的值进行了交换,在新标准库中,容器既提供成员函数版本的swap,也提供非成员函数版本的swap,非成员版本的swap在泛型编程中是非常重要的,统一使用非成员版本的swap是一个好习惯,但是有些情况下成员版本的swap会比非成员版本的swap更加高效,如果使用还需根据实际情况

  • 容器的insert成员的返回类型

        在新标准下,接受元素个数或范围的insert版本返回指向第一个新加入元素的迭代器(在旧版本的标准库中,这些操作返回void),如果范围为空,不插入任何元素,insert操作会将第一个参数返回通过使用insert的返回值,可以在容器中的一个特定位置反复插入元素。

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

第一次调用insert会将我们刚刚读入的string插入到iter所指向的元素之前的位置,insert返回的迭代器恰好指向这个新元素,所以每次循环将一个新元素插入到list首元素之前的位置。

  • 容器的emplace成员的返回类型

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

//在c的末尾构造一个Sales_data对象
c.emplace_back("978-0050", 25, 15.99); //正确 相当于先利用参数创建对象
c.push_back("978-0050", 25, 15.99);  //错误没有接受三个参数的push_back版本
c.push_back(Sales_data("978-0050", 25, 15.99));  //正确

在调用emplace_back时,会在容器管理的内存空间中直接创建对象,而调用push_back则会创建一个局部临时对象,emplace函数在容器中直接构造元素,传递给emplace函数的参数必须与元素类型的构造函数相匹配

  • pair类型

        pair是标准库类型,它定义在 #include <utility>,一个pair保存俩个数据成员,类似容器,pair是一个用来生成特定类型的模版,当创建一个pair时,我们必须提供俩个类型名,pair的数据成员将具有对应的类型,俩个类型不要求一样。与其他标准库类型不同,pair的数据成员是public的,俩个成员分别命名为firstsecond

pair<string, size_t> word_count;        //保存一个string和一个size_t
pair<string, vector<int>> line;            //保存string和vector<int>
pair上的操作:
pair<T1, T2> p(v1, v2);        //初始化
pair<T1, T2> p = { v1,v2 };  //初始化
make_pair(v1, v2);                             //返回一个用v1和v2初始化的pair,pair的类型从v1和v2的类型推断出来

创建返回pair对象的函数:(一个函数需要返回一个pair,在新标准下,我们可以对返回值进行列表初始化)

pair<string, int> process(vector<string>& v)
{
	if (!v.empty())
		return{ v.back(),v.back().size() };  //列表初始化
	else
		return pair<stirng, int>();  //隐式构造函数返回值(一个空pair)
}

在较早的C++版本中,不允许用花括号包围的初始化器来返回pair这种类型的对象,必须显式构造返回值
return pair<string, int>(v.back(), v.back().size());
我们还可以用make_pair来生成pair对象
return make_pair(v.back(), v.back().size());

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值