首页 > 其他分享 >vector

vector

时间:2024-05-10 23:09:04浏览次数:24  
标签:const cout 迭代 back vector push

[vector文档](vector - C++ Reference (cplusplus.com))
vector是序列容器,表示可以改变大小的数组。要使用vector,同样需要引入头文件

#include <vector>

vector与string

  • string中会有\0,vector<char>中不会出现\0
  • string可以进行字符串的拼接,vector<char>不可以

vector的构造

void test1() {
	vector<int> v1;
	v1.push_back(1);
	v1.push_back(2);
	v1.push_back(3);
	v1.push_back(4);
	cout << "v1:";
	for (size_t i = 0; i < v1.size(); ++i) {
		cout << v1[i] << " ";
	}
	cout << endl;

	vector<int> v2(v1);
	cout << "v2:";
	for (size_t i = 0; i < v2.size(); ++i) {
		cout << v2[i] << " ";
	}
	cout << endl;
}

vector的3种遍历方式

operatro[]、迭代器、范围for

void test2() {
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	//operator[]
	for (size_t i = 0; i < v.size(); ++i) {
		cout << v[i] << " ";
	}
	cout << endl;

	//迭代器
	vector<int>::iterator it = v.begin();
	while (it != v.end()) {
		cout << *it << " ";
		++it;
	}
	cout << endl;

	//范围for
	for (auto x : v) {
		cout << x << " ";
	}
	cout << endl;
}

3种类型的迭代器

void test3() {
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	//正向迭代 可读可写
	vector<int>::iterator it = v.begin();
	while (it != v.end()) {
		cout << *it << " ";
		++it;
	}
	cout << endl;

	//逆向迭代
	vector<int>::reverse_iterator rit = v.rbegin();
	while (rit != v.rend()) {
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
}

//只读
void print_vector(const vector<int>& v) {
	vector<int>::const_iterator it = v.begin();
	while(it != v.end()) {
		//*it = 1;
		cout << *it << " ";
		++it;
	}
	cout << endl;
}

const迭代器单独放到一个函数中,是因为只有const对象才需要const迭代器,在实际中不会直接定义const对象(没有意义),const对象基本都是在传参的过程中产生的,由于传参为了提高效率,基本都会使用&传参,而引用传参如果不改变对象,基本都会加const

容量相关

// 测试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';
		}
	}
}

从上面可以看出,随着数据的不断插入,增容的速度越来越慢,并且是按照1.5倍进行增容,但并不是说vector都是按照1.5倍进行增容,具体增容多少是和编译器的不同而有所改变。
还有就是增容的倍数并不是越大越好,倍数越大虽然可以减少增容的次数,但是有可能会导致浪费大量的空间。因此增多少是一种选择,各有利弊。

若是已经确定要存储元素的个数,可以提前将空间设置足够

void TestVectorExpandOP()
{
	vector<int> v;
	size_t sz = v.capacity();
	v.reserve(100); // 提前将容量设置好,可以避免一遍插入一遍扩容
	cout << "making bar 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';
		}
	}
}

insert()与erase()

void test5() {
	vector<int> v;
	v.push_back(1);
	v.push_back(2);
	v.push_back(3);
	v.push_back(4);

	v.insert(v.begin(), 0);
	v.insert(v.begin(), -1);
	for (auto x : v) {
		cout << x << " ";
	}
	cout << endl;

	v.erase(v.begin());
	for (auto x : v) {
		cout << x << " ";
	}
	cout << endl;
}

在上面中,erase并不能删除指定的数据,而vector中并没有find函数,所以此时我们需要引入algorithm, #include<algorithm>

//要求删掉2
vector<int>::iterator pos = find(v.begin(), v.end(), 2);
if (pos != v.end()) {
	v.erase(pos);
}
for (auto x : v) {
	cout << x << " ";
}
cout << endl;

find其实是一个函数模板,如下

template<class InputIterator, class T>
InputIterator find(InputIterator first, InputIterator last, const T& val) {
	while (first != last) {
		if (*first == val) return first;
		++first;
	}
	return last;
}

迭代器失效

迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)

  1. 引起底层空间改变的操作,迭代器可能失效

    void test6() {
    	vector<int> v;
    	v.push_back(1);
    	v.push_back(2);
    	v.push_back(3);
    	v.push_back(4);
    //迭代器失效
    	vector<int>::iterator it = v.begin();
    	v.push_back(5);
    	v.push_back(6);
    
    	while (it != v.end()) {
    		cout << *it << " ";
    		++it;
    	}
    	cout << endl;
    }
    

    从上面来看,由于在插入56的之前it已经被赋值,当插入56时,由于空间不够,需要开辟新的空间,销毁原来的空间,而it任然指向的是原来的那个空间,因此此时的迭代器就已经失效了。

  2. 删除操作——erase

    void test7() {
    	vector<int> v;
    	v.push_back(1);
    	v.push_back(2);
    	v.push_back(3);
    	v.push_back(4);
    	v.push_back(5);
    	v.push_back(6);
    
    	vector<int>::iterator it = v.begin();
    
    	for (auto x : v) {
    		cout << x << " ";
    	}
    	cout << endl;
    	//删除偶数
    	while (it != v.end()) {
    		if (*it % 2 == 0) {
    			v.erase(it);
    		}
            else {
                ++it;        
            }
    	}
    
    	for (auto x : v) {
    		cout << x << " ";
    	}
    	cout << endl;
    }
    

    在上面代码中,由于使用erase删除pos位置元素的时候,pos之后的元素会向前移动,此时的it没有改变,但是it所指向的元素发生了变化,变成了原来pos+1位置的元素,此时程序就崩溃了。而之后又要进行++it,因此就会漏掉对此时it所指向元素的判断。

    注意:在vscode中以上写法会导致程序崩溃,但在linux下的g++中,以上写法并不会崩溃,只是最后的结果会出错。

    因为erase返回的是被删除元素后一个位置的迭代器,所以正确的写法如下

    	while (it != v.end()) {
    		if (*it % 2 == 0) {
    			it = v.erase(it);
    		}
    		else {
    			++it;
    		}
    	}
    

标签:const,cout,迭代,back,vector,push
From: https://www.cnblogs.com/zhiheng-/p/18185452

相关文章

  • 初识vector
    一、定义和初始化vector1、初始化vector是模板而非类型,由vector生成的类型必须包含vector中元素的类型。如vector<int>。1、默认初始化vector<string>s;2、拷贝初始化注意:字面值不能构造vector对象vector<int>i;vecotr<int>i2(i);vector<int>i3=i;vector......
  • c语言实现vector及其相关函数(自存)
    #include<stdio.h>#include<stdlib.h>#definePREALLOC_MAX1024#defineDEFAULT_CAPACITY8typedefintE;typedefstruct{E*elements;//指向堆空间的数组intsize;//元素的个数intcapacity;//数组的容量}Vector;voidpush_back(Vect......
  • 一文详解C++的vector
    vector是C++中使用频率最高的标准库,可以在程序运行时动态改变其大小(例如添加或删除元素),因此又被称为动态数组。使用时,用户无需在意底层内存管理的细节,因为它已经帮你做了这件事情。使用前需要导入<vector>头文件,以下是vector的常见用法:1.创建vectorvector用于保存一组同类型的......
  • vector开二维数组&&深搜迷宫问题&&BFS
    vector<vector>vis(N+10(一维的大小),vector(N+10(二维的大小),0(初始化赋值)),step(N+10,vector(N+10,0));vector<vector>vis(N+10,vector(N+10)),step(N+10,vector(N+10));开数组大小一定要超过题目本身大小;#include<bits/stdc++.h>usingnamespacestd;#defineintl......
  • JDK源码分析-Vector
    概述Vector是Java集合中线程安全的动态数组,它也可以根据需要进行扩容和缩容,与ArrayList类似。但有一个重要的区别,Vector是同步的,也就是它的操作是线程安全的,在某些特定场景下是可以保证线程安全的,但同时也会带来性能损耗,因此在单线程环境通常还是推荐使用ArrayList。类图......
  • [ARC176E] Max Vector
    MyBlogs[ARC176E]MaxVector\(n=10\)其实有点误导性。其实这个题不是指数级的算法,而且贪心也不是很合理,同时“要么...要么...”有点像最小割。一次操作可以看成要求\(x_j\geqa_{i,j}\)或者\(y_j\geqa_{i,j}\)。考虑切糕的模型,建\(2n\)条链,割哪条边就表示第\(i\)个......
  • C++ Vector fundamental
    C++Vectorfundamental主要内容包括:引入头文件,如何创建并初始化,访问容量,增查删改;1.包含头文件#include<vector>#include<iostream>2.创建vectorvector<int>v;vector<char>v1;vector<string>v2;3.初始化一维vector初始化后不进行赋值,直接访问会报错;3.1ve......
  • TiDB Vector 抢先体验之用 TiDB 实现以图搜图
    本文首发自TiDB社区专栏:https://tidb.net/blog/0c5672b9转载请注明出处!前言最早知道TiDB要支持向量化的消息应该是在23年10月份左右,到第一次见到TiDBVector的样子是在今年1月初,当时dongxu在朋友圈发了一张图:去年我研究了一段时间的向量数据库,一直对TiDB向量特性......
  • 标量码与矢量码(Scalar code & Vector code)及一些后续知识
    标量码每一个码字在每一个节点上包含一个字节,向量码在每一个节点上包含若干字节,共同组合为一个超字节(superbyte),不同节点上的超字节共同组成一个码字。上面这个图是标量码,下面的是矢量码。用俗话说,标量码存的最小单位是一个数字,而矢量码存的最小单位是一个向量(下面这个图存的是向......
  • STL笔记 之 vector
    初识STLSTL,(StandardTemplateLibrary),即"标准模板库",由惠普实验室开发,STL中提供了非常多对信息学奥赛很有用的东西。vectorvetor是STL中的一个容器,可以看作一个不定长的数组,其基本形式为:vector<数据类型>名字;如:vector<int>v或vector<char>t。vector的基本操作先定......