C++_STL---vector

vector的相关介绍

  1. vector是表示可变大小数组的序列容器。我们学习的时候就可以把它看作是像数组一样的东西。
  2.  vector采用的连续存储空间来存储元素。也就是意味着我们可以采用下标对vector的元素进行访问,时间复杂度和数组一样高效,为O(1)。但是又不完全像数组,因为它的大小是可以动态改变的,而且它的大小会被容器自动处理。
  3. vector使用动态分配数组来存储它的元素,当新元素插入时,为了增加存储空间,这个数组需要被重新分配大小。
  4. vector分配空间策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。
  5. 与其它动态序列容器相比(deque, list and forward_list),vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入操作,效率更低。

想要了解更多关于vector的详细内容,请点击vector的文档介绍

vector的使用

注意:本章只介绍一些比较常用的接口

vector的相关定义

构造函数声明接口说明代码演示
vector()无参构造vector<int> v1;
vector(size_t n, const T& val = T())构造并初始化n个val

vector<int> v2(5, 10);

//初始化为5个值为10的整数

vector(const vector<T>& v)拷贝构造vector<int> v3(v2);
vector(InputIterator first, InputIterator last)使用迭代器进行初始化构造vector<int> v4(v3.begin(), v3.end());

 vector的空间增长问题

容量空间接口说明
resize改变vector的size
reserve改变vector的capacity

特别说明:

  • capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。vs是PJ版本STL,g++是SGI版本STL。
  • reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
  • resize在开空间的同时还会进行初始化,影响size。

vector的增删查改

vector的增删查改接口说明代码演示
insert(慎用)在pos位置之前插入valiterator insert(iterator pos, const T& val)
erase(慎用)删除pos位置数据iterator erase(iterator pos)
operator[]像数组一样访问T& operator[] (size_t n)

ps. 这些内容我会在下面讲解底层实现的代码,请耐心阅读

vector的迭代器失效问题

迭代器是什么?简单理解迭代器就是像指针一样的东西,我们在使用的时候不用关心其底层的细节,只需像指针一样来使用就可以。而迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,使用一块已经被释放(销毁)的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)。

底层空间扩容时,可能会引起迭代器失效

比如:resize、reserve、insert、assign、push_back等,都会引起迭代器失效

例:使用insert往某个位置插入元素时,可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,而在打印时,it还使用的是释放之前的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃。解决方法:给it重新赋值即可。

int main()
{
    vector<int> v1{1,2,3,4};
    // find函数:查找某个元素,如果找到了则返回该元素的迭代器,否则返回end()位置的迭代器
    vector<int>::iterator it = find(v1.begin(), v1.end(), 2);
    if (it != v1.end())
    {
        // 在查找的元素前插入200
        // v1.insert(it, 200); 这样写则会导致迭代器失效
    	it = v1.insert(it, 200); //给it重新赋值

    	cout << *it << " ";
    }
    cout << endl;
    return 0;
}

 指定位置元素的删除操作,可能会引起迭代器失效

例:erase的功能是删除pos位置的元素。erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了。

int main()
{
    vector<int> v1{1,2,3,4};
    vector<int>::iterator it = v1.begin();
    while (it != v1.end())
    {
    	if (*it % 2 == 0)
            //给it重新赋值,解决迭代器失效的问题
		    it = v1.erase(it); 
    	else
		    ++it;
    }
    return 0;
}

 注意:无论上面说的那种迭代器失效,都是针对vs所说;对于g++结果是不相同的

vector部分接口函数的底层实现

vector的初始化函数

//使用迭代器进行初始化构造
template <class InputIterator>
vector(InputIterator first, InputIterator last)
{
	while (first != last)
	{
		push_back(*first);
		++first;
	}
}
//n个val构造
vector(size_t n, const T& val = T())
{
	reserve(n); //提前开好空间,减小消耗
	for (size_t i = 0; i < n; i++)
	{
		push_back(val);
	}
}
//拷贝构造
vector(const vector<T>& v)
{
	reserve(v.capacity());
	for (const auto& e : v)
	{
		push_back(e);
	}
}

 vector的插入、删除函数

iterator insert(iterator pos, const T& val)
{
	assert(pos >= _start);
	assert(pos <= _finish);

	if (_finish == _end_of_storage)
	{
		size_t len = pos - _start; //记录pos的位置
		size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();
		reserve(newcapacity);

		pos = _start + len;        //更新新空间pos的位置 (迭代器失效的根本原因)
	}

	iterator end = _finish;
	while (end >= pos)             //从后往前依次挪动元素
	{
		*(end + 1) = *end;
		--end;
	}
	*pos = val;
	++_finish;

	return pos;                    
}
iterator erase(iterator pos)
{
	assert(pos >= _start);
	assert(pos < _finish);

	iterator begin = pos;
	while (begin < _finish - 1)  //从前往后挪动元素
	{
		*(begin) = *(begin + 1);
		++begin;
	}
	--_finish;

	return pos;
}
  • 26
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
STL是指标准模板库(Standard Template Library),它是C++语言的一部分,提供了一系列的模板类和函数,用于支持通用的数据结构和算法。STL的目标是提供高效、可重用和可扩展的组件,以便开发人员能够更轻松地编写高质量的代码。STL包含了许多常见的数据结构,如vector、list、set、map等,以及各种算法,比如排序、查找、遍历等。通过使用STL,开发人员可以更加高效地处理各种数据结构和算法的问题,提高代码的开发效率和质量。 在STL中,我们可以使用各种容器来存储和管理数据。例如,我们可以使用std::map来创建一个键值对的映射,其中每个键都有一个与之相关联的值。下面是一个示例代码,展示了如何创建和使用一个std::map对象: std::map<std::string, int> disMap() { std::map<std::string, int> tempMap{ {"C语言教程",10},{"STL教程",20} }; return tempMap; } std::map<std::string, int> newMap(disMap()); 在这个示例中,disMap()函数创建了一个临时的std::map对象,并初始化了其中的一些键值对。然后,使用移动构造函数将这个临时对象移动到了一个新的std::map对象newMap中。最终,我们可以通过newMap对象来访问和操作这些键值对。 综上所述,STLC++中的标准模板库,提供了一系列的模板类和函数,用于支持通用的数据结构和算法。STL的使用可以提高代码的开发效率和质量,并且通过各种容器和算法,可以方便地处理各种数据结构和算法的问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [C++ STL详解超全总结(快速入门STL)](https://blog.csdn.net/qq_50285142/article/details/114026148)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [【C++实验】阅读STL源码并分析](https://blog.csdn.net/qq_35760825/article/details/125311509)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值