1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > c++模板类vector成员函数

c++模板类vector成员函数

时间:2022-10-10 04:39:44

相关推荐

c++模板类vector成员函数

一.构造函数

vector类提供了多个构造函数,可以根据需要灵活地使用这些函数创建vector对象。

1. explicit vector (const allocator_type& alloc = allocator_type());

默认构造函数。创建一个空的vector对象。

alloc是一个缺省参数,用来指定要使用的空间适配器。不需要对其进行赋值,使用STL提供的默认的空间适配器即可。缺省参数详见:百度百科——缺省参数、【C++】缺省参数

比如:vector<int> temp; 使用这样的方式来创建vector对象时会调用该默认构造函数。

只是声明但没有初始化,编译器将不会为其分配内存空间。需要使用该temp对象调用成员函数resize()来申请空间,或者调用push_back()方法向容器插入元素。

2. vector (size_type n, const value_type& val, const allocator_type& alloc = allocator_type());

创建一个包含n个元素的vector对象,其中每个元素都被初始化为value。

其中,val也是一个缺省参数,如果没有为其传入实参,那么默认使用0来初始化这些元素。

比如:vector<int> temp(3); //temp包含3个int型的0

vector<int> temp1(4, 1); //temp1包含4个int型的1

3. template <class InputIterator>

vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());

创建一个vector对象,并使用一组有序数据中部分元素来初始化这个vector对象。

first和last是两个迭代器,分别表示所选的部分元素的起始地址和结束地址。

比如:int a[5] = {1, 2, 3, 4, 5}; //有序数据是一个int型数组

vector<int>temp(a, a+4); //使用数组a的前四个元素初始化容器temp

vector<int>temp1(temp.begin(), temp.end()-1); //此时,有序数据是指int型容器temp,这里表示使用容器temp除最后一个元素外的所有元素来初始化temp1,最终结果是temp1有三个元素,分别是1,2,3

4. vector (const vector& x, const allocator_type& alloc);

拷贝构造函数。使用一个vector对象来初始化一个新的vector对象。

比如在第3点中,我们使用temp来初始化temp1:

vector<int>temp1(temp); //temp1包含四个元素,分别是1,2,3,4

另外c++11新增了移动构造函数和初始化器列表构造函数,详见std::vector::vector

二.生成迭代器

1. 正向迭代器

①iterator begin() noexcept; //返回指向容器第一个元素的迭代器

②const_iterator begin() const noexcept; //同①,但容器中的元素是const类型的

③iterator end() noexcept; //返回指向容器最后一个元素后面一个元素的迭代器(假想的一个元素)

④const_iterator end() const noexcept; //同③,但容器中的元素是const类型的

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp(5, 10);vector<int>::iterator my_iterator = temp.begin();for ( ; my_iterator != temp.end(); my_iterator++){cout << *my_iterator << endl;}}

编译运行结果:

从示例可以看出,迭代器的使用与指针类似。但是指针本身是个内存地址,可以打印出来;而输出迭代器本身是没有意义的。

迭代器实际上是个iterator类型的变量,以及下面的反向迭代器(reverse_iterator类型的变量),都是vector类的数据成员,在调用这些生成迭代器的函数时,需要使用类型匹配的变量来接收函数返回值。

对迭代器本身进行加减操作类似于对数组名进行加减操作,将改变迭代器的指向。对于正向迭代器而言,对其进行加操作会使其向后移动,即指向下标更大的元素。

2. 反向迭代器

①reverse_iterator rbegin() noexcept; //返回指向容器最后一个元素的迭代器(反向迭代器)

②const_reverse_iterator rbegin() const noexcept; //同①

③reverse_iterator rend() noexcept; //返回指向容器第一个元素的迭代器

④const_reverse_iterator rend() const noexcept;

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp = { 1,2,3,4,5 };vector<int>::reverse_iterator my_iterator = temp.rbegin();cout << *(my_iterator + 1) << endl; //利用反向迭代器输出倒数第二个元素my_iterator = temp.rend();cout << *(my_iterator - 1) << endl; //利用反向迭代器输出第一个元素}

编译运行结果:

从示例可以看出,rend()函数返回的是指向容器最后一个元素的迭代器,这一点与end()是有区别的。

另外,对于反向迭代器而言,对其进行加操作,会使其向前移动,即指向下标更小的元素。

三.向末尾添加或删除元素

void push_back (const value_type& val);

void push_back (value_type&& val);

void pop_back();

push_back()函数可以在当前容器的最后一个元素后面添加一个元素,实现容器的动态拓展。

变量类型value_type是容器中元素的类型,在容器中定义为其第一个模板参数( T )的别名,val是待添加的元素。模板类vector提供了push_back()函数的重载,用于操作const类型的元素。

pop_back()函数可以删除当前容器的最后一个元素,此时容器的大小也会减1。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp;for (int i = 0; i < 5; i++){temp.push_back(i); //向容器temp填入五个int型元素0,1,2,3,4}temp.pop_back();//删除最后一个元素,只调用一次,因此删除 4for (vector<int>::iterator my_iterator = temp.begin(); my_iterator != temp.end(); my_iterator++){cout << *my_iterator << endl;}}

编译运行结果:

四.插入元素

前面我们使用成员函数push_back()向容器最后面添加元素,另外vector还提供了insert()方法用于向容器的任意位置插入元素,insert()插入元素不会覆盖,而是将该位置之前的元素和后面所有的元素向后移动。不仅可以有效地增加元素数量,更关键的是提供了更加有效的、方便的对数据的操作方式。

但是容器的是以动态数组作为基础实现的,插值的操作会导致对后面的所有的元素也进行移位,因此强大的功能性是以性能作为代价的。C++11新特性(26)- 容器的insert成员

vector类提供了insert()函数的多个重载,用于实现不同的插入方式。

1. iterator insert (const_iterator position, const value_type& val);

在指定位置处插入单个元素。调用完后,容器position处的元素将变为val。

position是待插入的元素在容器中的位置,由迭代器指定,因此该参数需要由第二点中的某个函数返回。val是待插入的元素。

比如:temp.insert(temp.begin() + 2, 6); //在容器temp的第三个元素处插入一个6

2. iterator insert (const_iterator position, size_type n, const value_type& val);

在指定位置处插入多个相同的元素。

n表示待插入的元素的数量。

比如:temp.insert(temp.begin() + 2, 3, 4); //在容器temp的第三四五个元素处插入三个4

3. template <class InputIterator>

iterator insert (const_iterator position, InputIterator first, InputIterator last);

在指定位置处插入另一容器的部分元素。这部分元素由另一容器的两个迭代器指定。

比如:temp1.insert( temp1.begin()+2, temp.begin()+3, temp.end() ); //将容器temp除了前三个元素外的所有元素插入到容器temp1的第二个元素后面。

4. iterator insert (const_iterator position, value_type&& val);

将其他容器中的某个元素移动到指定位置。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp,temp1;for (int i = 0; i < 5; i++)temp.push_back(i);temp1.insert(temp1.begin(), move(*(temp.begin() + 2)));for (vector<int>::iterator my_iterator = temp.begin(); my_iterator != temp.end(); my_iterator++){cout << *my_iterator << endl;}for (vector<int>::iterator my_iterator = temp1.begin(); my_iterator != temp1.end(); my_iterator++){cout << *my_iterator << endl;}}

编译运行结果:

注意:move()函数移动的是具体的值,所有不能传入迭代器作为参数,而应使用解引用取到的具体的元素的值。

5. iterator insert (const_iterator position, initializer_list<value_type> il);

将初始化列表il中的元素插入到容器指定位置处。il是使用聚合法表示的元素。

比如:temp.insert(temp.begin(), {4, 5, 6}); //在容器temp开头插入三个int型元素4,5,6

五.删除元素

iterator erase (iterator position);

iterator erase (const_iterator first, const_iterator last);

成员函数erase()有两个重载,可用于从容器中删除某个元素,或删除一连串元素,其中这一连串的元素是由两个迭代器指定的。

比如:temp.erase( temp.begin() + 2); //删除容器temp第三个元素

temp.erase( temp.begin() + 2, temp.end() ); //删除容器temp第三个及后面所有元素

六.清空容器

void clear() noexcept;

成员函数clear()用于将容器里面的所有元素清空,调用完容器的大小将会为0。

对于一个容器来说,如果要对其多次重用,需要在每次使用后将其清空,因为常用到的push_back()函数只会向容器后面添加元素,多次重用时,容器中以前的数据是不会被覆盖的。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp;for (int i = 0; i < 500; i++){temp.push_back(1);}temp.clear();temp.push_back();for (vector<int>::iterator my_iterator = temp.begin(); my_iterator != temp.end(); my_iterator++){cout << *my_iterator << endl;}}

编译运行结果:

七.测试容器是否为空

bool empty() const;

成员函数empty()并不是清空容器,而是判断容器是否为空。它不会对容器内的元素做任何修改,清空容器见第六点。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp;if (!temp.empty()){cout << temp[0] << endl;}else{cout << "empty" << endl;}}

编译运行结果:

八.返回引用(访问元素)

1. 返回第一个元素的引用

reference front();

const_reference front() const;

成员函数front()用于返回容器第一个元素的引用。返回类型reference和const_reference是对容器中元素类型的引用,如果元素是int类型,那么实际返回类型是int&。

前面生成迭代器的函数返回的是指向元素的迭代器,返回引用的函数返回的是指定元素的值。同样,模板类vector提供了对front()函数的重载,根据容器存储的元素是否是const类型自动选择对应的函数。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp = { 1,2,3,4,5 };vector<int>::reverse_iterator my_iterator = temp.rend();if (temp.front() == *(my_iterator - 1)){cout << "yes" << endl;}int&b = temp.front();b = 10;cout << temp[0] << endl;}

编译运行结果:

使用front()相当于对begin()获取的迭代器解引用,如表达式temp.front() = *( temp.begin() )的结果为真

2. 返回最后一个元素的引用

reference back();

const_reference back() const;

成员函数back()用于返回容器最后一个元素的引用。用法与back()一致,详见front()。

3. 返回任意位置元素的引用——at()函数

reference at (size_type n);

const_reference at (size_type n) const;

前面的成员函数back()和front()只能返回容器第一个和最后一个元素的引用,而at()函数可以返回容器中任意一个元素的引用。

返回类型在前面front()已经提过,不再赘述;参数n表示所要访问的元素在容器中的位置(即下标),也是从0开始。

注意:at()函数会自动检查n是否在容器元素的下标范围内,如果n大于或等于其大小,则引发out_of_range异常。而同样是访问元素的值,通过下标访问则不会检查。at()函数可以有效的避免下标访问可能存在的访问越界问题。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp = { 1,2,3,4,5 };cout << temp.at(10) << endl;;}

编译运行结果:

4. 返回任意位置元素的引用——运算符[]重载

reference operator[] (size_type n);

const_reference operator[] (size_type n) const;

该运算符函数与前面的at()函数有几乎一样的功能,但是正如前面所说,如果n超过了容器当前的大小,该运算符函数会引发out_of_range异常,而at()不会。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp = { 1,2,3,4,5 };for (int i = 0; i < temp.size(); i++)cout << temp.operator[](i) << endl; //显示调用[]运算符重载cout << temp[0] << endl;//隐式调用[]运算符重载

编译运行结果:

另外,除了这些成员函数外,还可以通过对迭代器解引用访问元素的值,这一点在前面多出示例中使用过。

九.赋值(复制、拷贝)

对容器赋值使用新的元素替换容器当前的元素,容器的大小也会被相应的修改。容器有两种重新赋值的方式,重载的赋值运算符和assign()成员函数。

参见第一部分中的拷贝构造函数。

1. 赋值运算符重载

①vector& operator= (const vector& x);

将容器x中的所有元素复制到等号左侧容器中,x的修饰词const确保复制时x内的元素不被修改

②vector& operator= (vector&& x);

③vector& operator= (initializer_list<value_type> il);

使用初始化列表对容器赋值。该方法将初始化列表il中的元素全部复制到当前容器中,替换已有的元素。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp = { 1,2,3,4,5 }; //调用列表初始化构造函数创建vector对象tempvector<int> temp1 = { 0,1 };//调用列表初始化构造函数创建vector对象temp1temp1.operator=({0,1,2}); //(显式)调用赋值运算符重载③对temp1赋值cout << temp1[2] << endl;temp1 = { 1,2,3,4,5 }; //(隐式)调用赋值运算符重载③对temp1赋值cout << temp[3] << endl;}

编译运行结果:

2. 成员函数assign()

①template <class InputIterator> void assign (InputIterator first, InputIterator last);

将源容器中的部分元素赋给目标容器。这部分元素由源容器的两个迭代器指定。

②void assign (size_type n, const value_type& val);

将n个相同的元素赋给目标容器,每个元素都是参数val的副本。value_type是容器中元素的类型。

③void assign (initializer_list<value_type> il);

使用初始化列表对容器赋值。该方法将初始化列表il中的元素全部复制到当前容器中,替换已有的元素。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp = { 1,2,3,4,5 };vector<int> temp1 = { 0,1 };temp1.assign(temp.begin() + 1, temp.end()); //temp1包含四个元素2,3,4,5for (int i = 0; i < temp1.size(); i++)cout << temp1[i] << endl ;temp1.assign({ 1,2,3,4,5 }); //temp1包含五个元素1,2,3,4,5for (int i = 0; i < temp1.size(); i++)cout << temp1[i] << endl;}

编译运行结果:

十.返回指针(访问元素)

value_type* data() noexcept;

const value_type* data() const noexcept;

vector中的元素除了可以使用迭代器和返回引用的函数访问外,还可以使用指针来访问每一个元素,该指针由成员函数data()返回。vector提供了data()函数的重载,调用时会根据容器内的元素是否是const类型来自动匹配。

data()函数返回指向容器内部使用的数组的第一个元素的指针,这表明调用该函数并不能直接访问元素,但是可以通过该指针来访问或修改元素。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp = { 1,2,3,4,5 };int* ptr = temp.data();for (int i = 0; i < temp.size(); i++){cout << *(ptr + i) << endl;}}

编译运行结果:

十一.容器大小相关

前面多次提到了容器的大小,但是这些所说的“大小”并不是完全一样的概念,有的表示容器当前存储的元素的个数大小,有的表示容器的容量大小(所分配的内存空间的大小)。

1. 成员函数size()

size_type size() const noexcept;

size()函数返回容器当前的元素个数。反映了调用该方法时容器一共存储了多少个元素。

返回类型size_type是一个无符号的整数类型

2. 成员函数capacity()

size_type capacity() const noexcept;

capacity()函数返回为当前的容器分配的存储空间的大小,也是以元素个数为单位。capacity()函数的返回值是一个偏向容量的概念。

容器的基础是数组,也就是说容器的底层是用数组来存储数据的。容器内部会根据元素个数的增长,对这个底层数组的大小进行扩展。这时有这样的疑惑,数组的大小在它声明的时候不是已经确定了吗,怎么进行扩展?这里的扩展是指创建一个新的更大的数组,然后将之前使用的数组中的内容复制到这个更大的数组中。

比如我们使用vs,通过向容器中push_back()更多的元素,然后查看它的capacity,就会发现这样一组数据:42 63 94 141 211 316 474 …

也就是说,如果容器中当前的元素个数(size()的返回值)没有超过42,那么为这个容器分配的存储空间的容量就是42,即底层实现的数组的大小是42;如果向里面再存入元素,使其元素个数超过42,但没有达到63,那么底层就会创建一个新的数组,数组的大小是63;以此类推……

注意:容器的底层实现是数组,容器的无限增长是通过不断地创建更大的数组来替代当前使用的数组。当容器中存储的元素的个数达到或超过当前容量时,容器会自动扩展(底层的数组),即重新分配存储空间。这样可以达到节省内存的目的。

3. 成员函数max_size()

size_type max_size() const noexcept;

max_size()函数返回当前系统环境下,任意vector对象可以容纳的元素的个数。这是一个理论上的容量的最大值,由系统和库实现决定的,与程序无关,无论容器的元素个数怎么增长,该函数的返回值都不会变化。比如查看本机的vector理论容量:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp;cout << temp.max_size() << endl;}

编译运行结果:

4. 成员函数resize()

void resize (size_type n);

void resize (size_type n, const value_type& val);

resize()函数用来调整容器大小,使其包含n个元素。如果调用该方法时,容器包含的元素个数超过n,则会保留前n个元素,删除其他元素(并销毁这些元素);如果容器包含的元素个数小于n,那么会在容器后面持续插入元素直至元素个数达到n,以达到扩展容器的效果,这些插入的元素是由参数val决定的,如果指定了参数val,那么这些元素会被初始化为val的副本,否则会被初始化为默认值。

另外,如果n超过了当前容器的容量,那么容器会自动扩展(底层的数组),即重新分配存储空间;而如果n小于当前容器的容量的话,容器并不会重新分配存储空间。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp;for (int i = 0; i < 111; i++)temp.push_back(i);cout << temp.capacity() << endl;temp.resize(400); //超出当前容量,这里会重新分配内存空间cout << temp.capacity() << endl;temp.resize(111); //不会重新分配内存空间cout << temp.capacity() << endl;}

编译运行结果:

5. 成员函数reserve()

void reserve (size_type n);

人为设置容器的容量。reserve()函数会保证容器达到至少能容纳n个元素的容量。如果n大于当前容器的容量,则调用该函数时,会为容器重新分配存储空间,将其容量提升为n;其他情况下,调用该函数不会引起存储空间的重新分配,容器当前的容量不受影响。

前面第2点capacity()函数中我们提到过,自动分配存储空间时,容器的容量是一些离散的固定值,但是使用reserve()的时候,容量的容量可以是任意正整数。

注意:如果参数n大于容量的最大值(max_size()返回),会引发length_error异常

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp;for (int i = 0; i < 111; i++)temp.push_back(i);cout << temp.capacity() << endl;temp.reserve(150);cout << temp.capacity() << endl;}

编译运行结果:

6. 成员函数shrink_to_fit()

void shrink_to_fit();

shrink_to_fit()函数会调整容器容量以适应容器大小。有时候向容器里写入了太多的元素,导致这个容器的容量自动增长得很大,并且为这个容器分配了很大的存储空间。如果此时元素个数变为一个较小的值(比如使用resize()调整容器大小),可以调用shrink_to_fit()函数来获取一个与此时的容器大小接近的容量,释放多余的暂时用不到的存储空间。

示例:

#include<iostream>#include<vector>using namespace std;int main(){vector<int> temp(1000, 6);cout << temp.capacity() << endl;temp.resize(100);cout << temp.capacity() << endl;temp.shrink_to_fit();cout << temp.capacity() << endl;}

编译运行结果:

十二. 交换两个容器内容

void swap (vector& x);

略... ...

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。