【C++】vector的认识与使用

大柏怎么被偷了 2024-07-24 17:35:01 阅读 93

vector的认识与使用

认识vectorvector的使用Member functions(成员函数)构造函数(constructor)析构函数(destructor)赋值构造函数(operator=)

Iterators(迭代器)beginendrbeginrend

Capacity(容量)sizemax_sizeresizecapacityemptyreserve

Element access(元素访问)operator[]atfrontback

Modifiers(修饰符)assignpush_backpop_backinserteraseswapclear

认识vector

vector:翻译过来是向量,矢量。但是学习过来,给我的感觉类似于顺序表,或者说是数组??

在这里插入图片描述

std::vectortemplate < class T, class Alloc = allocator > class vector; // generic template

在这里插入图片描述

class T代表的是一个类型,是成员变量。

在这里插入图片描述

allocator代表的是空间配置器。

vector是一个可以改变大小的代表数组的序列容器。类似于数组,vector使用连续的存储位置存储元素,意味着可以采用下标对vector的元素进行访问,并且和数组一样高效。但是不同于数组,其大小可以随着存储被容器自动处理而动态改变。本质来将,vector使用动态分配数组来存储它的元素。对于数组而言,当新元素被插入的时候,数组为了增加存储空间需要被重新分配大小。其做法是,分配一个新的数组,然后将全部元素移到这个数组。就时间而言,这是一个相对代价高的任务,vector并不会每次都重新分配大小。vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔下进行增长的,以至于在末尾插入一个元素的时候可以提供摊销的恒定时间复杂度。因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。与其他动态序列容器相比(deque,list,forward_list),vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其他不在末尾的删除和插入操作,效率更低。比起list和forward_list统一的迭代器和引用更好。

vector的使用

在使用STL的三个境界:能用,明理,能扩展。

在介绍vector的时候,需要结合文档来学习:链接: vector

Member functions(成员函数)

构造函数(constructor)

在这里插入图片描述

std::vector::vector构造vector构造一个vector容器,根据使用的构造函数版本初始化其内容default (1)

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

无参构造函数(默认构造)

构造一个没有任何元素的空的容器

<code>vector<int> v1;

fill (2)

explicit vector (size_type n, const value_type& val = value_type(),

const allocator_type& alloc = allocator_type());

fill构造函数

构造一个有n个元素的容器,每一个元素都是val的值。

vector<int> v2(10, 1);

vector<char> v3(5, 'x');

vector<string> v4(6, "hello");

range (3)

template < class InputIterator >

vector (InputIterator first, InputIterator last,

const allocator_type& alloc = allocator_type());

range构造函数

构造一个函数,其中包含与范围(first,last)一样长的元素,每一个元素以相同的顺序从该范围内的相应元素构造。

int a[4] = { 4,27,22,20 };

vector<int> v5(a, a + 4);

这种方式可以使用自己的迭代器进行构造:

vector<int> v1(10, 1);

vector<int> v2(v1.begin(), v1.end());

同时也可以使用其他容器的迭代器:

string str("hello world");

vector<char> v(str.begin(), str.end());

【说明】STL中包括容器(存储数据)和算法(对数据进行处理),在算法中有一个sort()函数,头文件为< algorithm >,就是使用迭代器进行排序的。

在这里插入图片描述

下面进行升序排序操作:

<code>int a[4] = { 4,27,22,20 };

vector<int> v(a, a + 4);

sort(v.begin(), v.end());

for (size_t i = 0; i < v.size(); ++i)

{

cout << v[i] << " ";

}

cout << endl;

下面进行降序排序操作:

int a[4] = { 4,27,22,20 };

vector<int> v(a, a + 4);

greater<int> g;

sort(v.begin(), v.end(), g);

for (size_t i = 0; i < v.size(); ++i)

{

cout << v[i] << " ";

}

cout << endl;

降序操作也可以写成匿名对象的方式:

int a[4] = { 4,27,22,20 };

vector<int> v(a, a + 4);

sort(v.begin(), v.end(), greater<int>());

for (size_t i = 0; i < v.size(); ++i)

{

cout << v[i] << " ";

}

cout << endl;

其他容器也是允许被排序的,例如string类,数组等等。

copy (4)

vector (const vector& x);

拷贝构造

构造一个函数,其中包含x中的每一个元素的副本,顺序相同。

vector<int> v6(10, 2);

vector<int> v7(v6);

【注意】了解vector的基本原理之后,可以觉得vector已经可以代替string了,但是这是不可取的。

vector< char > 不能代替string的原因:

首先俩者是存在不同点的,string后面保证会出现’\0’,这是为了像C兼容,而vector是不会自动出现"\0"的,需要手动添加,而手动添加的代价就是难免会忘记。同时,string的接口是要比vector更加丰富的,很多关于string的专业接口函数。例如:vector的比较大小相较于string类的比较大小是没有意义的。

vector是针对所有类型的,同时vector也是可以引用string类的。

vector<string> v;

可以向string类型的vector添加字符串:

string name1("大柏");

v.push_back(name1);

这里可以替换成匿名对象

v.push_back(string("大柏"));

也可以直接添加字符串:

v.push_back("大柏");

需要注意的是,这里直接添加字符串是相当于隐式类型转换,将字符串先进行拷贝构造,然后再进行构造,系统会直接优化成直接构造。

析构函数(destructor)

在这里插入图片描述

std::vector::~vector~vector();析构函数销毁容器对象

赋值构造函数(operator=)

在这里插入图片描述

std::vector::operator=copy (1)

vector& operator= (const vector& x);分配内容

<code>vector<int> v1(10, 5);

vector<int> v2;

v2 = v1;

Iterators(迭代器)

begin

在这里插入图片描述

std::vector::beginiterator begin();const_iterator begin() const;返回指向开始的迭代器

end

在这里插入图片描述

std::vector::enditerator end();const_iterator end() const;返回指向结尾的迭代器

【注意】迭代器无const可以进行读写,而有const只能进行度。

<code>vector<int> v(10, 5);

vector<int>::iterator it = v.begin();

while (it != v.end())

{

cout << *it << " ";

++it;

}

cout << endl;

在这里插入图片描述

rbegin

在这里插入图片描述

std::vector::rendreverse_iterator rend();const_reverse_iterator rend() const;返回指向反向结尾(开头)的反向迭代器

rend

在这里插入图片描述

std::vector::rendreverse_iterator rend();const_reverse_iterator rend() const;返回指向反向开头(结尾)的反向迭代器。

使用反向迭代器也可以进行排降序:

<code>int a[4] = { 4,27,22,20 };

vector<int> v(a, a + 4);

sort(v.rbegin(), v.rend());

for (size_t i = 0; i < v.size(); ++i)

{

cout << v[i] << " ";

}

cout << endl;

在这里插入图片描述

Capacity(容量)

size

在这里插入图片描述

std::vector::sizesize_type size() const;返回大小

<code>vector<int> v(10, 5);

cout << v.size() << endl;

max_size

在这里插入图片描述

std::vector::max_sizesize_type max_size() const;返回最大存储

【注意】不同的平台,最大的存储值不同

<code>vector<int> v(10, 5);

cout << v.max_size() << endl;

resize

在这里插入图片描述

std::vector::resizevoid resize (size_type n, value_type val = value_type());改变大小

<code>vector<int> v(10, 5);

v.resize(20, 1);

for (size_t i = 0; i < v.size(); ++i)

{

cout << v[i] << " ";

}

cout << endl;

capacity

在这里插入图片描述

std::vector::capacitysize_type capacity() const;返回分配存储容量的大小

下面是一段测试默认扩容机制

<code>// 测试vector的默认扩容机制

void TestVectorExpand()

{

size_t sz;

vector<int> v;

sz = v.capacity();

cout << "making v grow:\n";

for (int i = 0; i < 100; ++i)

{

v.push_back(i);

if (sz != v.capacity())

{

sz = v.capacity();

cout << "capacity changed: " << sz << '\n';

}

}

}

使用这段代码分别在vs环境下和gcc环境下测试会发现,vs下capacity是以1.5倍增长的,而gcc环境下capacity是以2倍增长的。具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。

empty

在这里插入图片描述

std::vector::emptybool empty() const;测试容器是否为空

<code>vector<int> v1(10, 5);

vector<int> v2;

cout << v1.empty() << endl;

cout << v2.empty() << endl;

reserve

在这里插入图片描述

std::vector::reservevoid reserve (size_type n);请求改变容量

<code>vector<int> v(10, 5);

v.reserve(30);

cout << v.capacity() << endl;

【注意】

1.使用reserve时是不允许使用下标[ ]的,这是因为下标[ ]在使用时需要调用size,而reserve不会改变size。

2.使用reserve需要添加数据时,可以使用push_back;使用resize添加数据时,可以使用下标+[ ]。这是因为reserve只能开辟空间,并不能改变size大小;而resize不仅可以开辟空间,同时也会改变size

Element access(元素访问)

operator[]

在这里插入图片描述

std::vector::operator[]reference operator[] (size_type n);const_reference operator[] (size_type n) const;访问元素

<code>vector<int> v(10, 5);

for (size_t i = 0; i < v.size(); ++i)

{

v[i] = i;

}

at

在这里插入图片描述

std::vector::atreference at (size_type n);const_reference at (size_type n) const;访问元素

<code>vector<int> v(10, 5);

for (size_t i = 0; i < v.size(); ++i)

{

v.at(i) = i;

}

【注意】使用下标+[ ]与at基本没有差别,唯一的差距是,使用下表+[] 报错时会断言,而使用at报错时会抛异常。

front

在这里插入图片描述

std::vector::frontreference front();const_reference front() const;访问第一个元素

<code>int a[4] = { 4,27,22,20 };

vector<int> v(a, a + 4);

cout << v.front() << endl;

back

在这里插入图片描述

std::vector::backreference back();const_reference back() const;访问最后一个元素

<code>int a[4] = { 4,27,22,20 };

vector<int> v(a, a + 4);

cout << v.back() << endl;

Modifiers(修饰符)

assign

在这里插入图片描述

std::vector::assignrange (1)

template < class InputIterator>

void assign (InputIterator first, InputIterator last);fill (2)

void assign (size_type n, const value_type& val);分配元素内容

<code>vector<int> v(10, 5);

v.assign(20, 1);

for (size_t i = 0; i < v.size(); ++i)

{

cout << v[i] << " ";

}

cout << endl;

push_back

在这里插入图片描述

std::vector::push_backvoid push_back (const value_type& val);在后面添加元素

<code>vector<int> v(10, 5);

v.push_back(1);

for (size_t i = 0; i < v.size(); ++i)

{

cout << v[i] << " ";

}

cout << endl;

pop_back

在这里插入图片描述

std::vector::pop_backvoid pop_back();删除最后一个元素

<code>int a[4] = { 4,27,22,20 };

vector<int> v(a, a + 4);

v.pop_back();

for (size_t i = 0; i < v.size(); ++i)

{

cout << v[i] << " ";

}

cout << endl;

insert

在这里插入图片描述

std::vector::insertsingle element (1)

iterator insert (iterator position, const value_type& val);fill (2)

void insert (iterator position, size_type n, const value_type& val);range (3)

template < class InputIterator >

void insert (iterator position, InputIterator first, InputIterator last);插入元素

<code>int a[4] = { 4,27,22,20 };

vector<int> v(a, a + 4);

v.insert(v.begin() + 2, 15);

for (size_t i = 0; i < v.size(); ++i)

{

cout << v[i] << " ";

}

cout << endl;

erase

在这里插入图片描述

std::vector::eraseiterator erase (iterator position);iterator erase (iterator first, iterator last);删除元素

<code>int a[4] = { 4,27,22,20 };

vector<int> v(a, a + 4);

v.erase(v.begin() + 1);

for (size_t i = 0; i < v.size(); ++i)

{

cout << v[i] << " ";

}

cout << endl;

swap

在这里插入图片描述

std::vector::swapvoid swap (vector& x);交换内容

<code>int a[4] = { 4,27,22,20 };

vector<int> v1(a, a + 4);

vector<int> v2(10, 5);

v1.swap(v2);

clear

在这里插入图片描述

std::vector::clearvoid clear();清理内容

<code>vector<int> v2(10, 5);

v2.clear();



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。