<C++>STL->vector

发布时间:2024年01月22日

vector的介绍

vector的使用文档

  • vector是一个可改变数组大小的序列容器
  • vector和数组一样采取连续的空间存放数据,可以使用方括号访问vector的元素,和数组一样高效。但是vector的大小可以动态增长,而数组不行
  • 实际上vector内部使用一个动态分配的数组存放数据。当插入新元素时,数组会按需重新分配大小为了增加存储空间。其做法是,分配一个新的数组,然后将所有元素移动到这个数组中。这是一个比较耗时间的策略,因此每当插入一个新元素时,vector并不会每次重新分配大小。
  • vector分配策略:vector会分配一些额外的空间用来适应插入元素时的增长,因此实际存储空间比当前元素所占用存储空间要大。不同的库采用不同策略平衡内存使用和重新分配,但无论如何,重新分配只能以对数增长的大小间隔进行,以便在向量末尾插入各个元素可以提供摊销常数时间复杂度
  • 与数组相比,vector会消耗更多的内存换取管理存储和更高效的动态增长的能力
  • 相比于其他动态增长的容器,vector获取元素和尾部插入删除元素更加高效;对于中间某一个元素插入删除时的效率没有其他容器高效,并且迭代器和引用的一致性不如列表和单向列表。

vector的使用

构造函数

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 空初始化:调用默认构造函数,没有元素
  2. 填充构造函数:使用nval初始化vector,每一个元素的值都是val
  3. 范围构造函数:使用[First, Last)中的元素一次初始化vector的每一个元素
  4. 拷贝构造函数:使用已存在的vector初始化新的vector
void test1()
{
	string str("hello world");
	vector<int> v1;			//vector是一个类模板,显示模板实例化int
	vector<int> v2(3, 1);	    //填充构造,3个1初始化v2;
	vector<char> v3(str.begin(), str.end());
    					      //范围构造
	vector<int> v4(v2);		 //拷贝构造
	for (auto e : v1)
	{
		cout << e;   	       //输出为空
	}
	cout << endl;
	for (auto e : v2)
	{
		cout << e << " ";     //1 1 1
	}
	cout << endl;
	for (auto e : v3)
	{
		cout << e;		   //hello world
	} 
	cout << endl;
	for (auto e : v4)
	{
		cout << e << " ";    //1 1 1
	}
	cout << endl;
}

赋值重载

operator=image-20240116103104495

  1. 功能:将其他vector的内容替换当前vector的值
  2. 参数:相同类型的vector
  3. 返回值:*this

demo:

// vector assignment
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> foo (3,0);
  std::vector<int> bar (5,0);

  bar = foo;
  foo = std::vector<int>();

  std::cout << "Size of foo: " << int(foo.size()) << '\n';//Size of foo: 0
  std::cout << "Size of bar: " << int(bar.size()) << '\n';//Size of bar:  3 
  return 0;
}

迭代器

string一样,vector是数据连续存储的容器,因此迭代器是指针。

begin/end

beginimage-20240116104257101

  1. 功能:返回容器第一个元素的指针
  2. 参数:迭代器函数的参数为空
  3. 返回值:如果容器是只读的,返回一个只读的迭代器;如果容器可读可写,返回一个可读可写的迭代器。

end外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 功能:返回指向vector最后一个元素的下一个位置的迭代器。
  2. 参数:迭代器函数的参数为空
  3. 如果容器是只读的,返回一个只读的迭代器;如果容器可读可写,返回一个可读可写的迭代器。

demo:

// vector::begin/end
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;
  for (int i=1; i<=5; i++) myvector.push_back(i);		

  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it = myvector.begin() ; it != myvector.end(); ++it)
    std::cout << ' ' << *it;						//1 2 3 4 5
  std::cout << '\n';

  return 0;
}

rbegin/rend

rbeginimage-20240116105141291

  1. 功能:返回指向vector最后一个元素反向迭代器
  2. 参数:反向迭代器函数的参数为空
  3. 返回值:如果容器是只读的,返回一个只读的反向迭代器;如果容器可读可写,返回一个可读可写的反向迭代器。

rendimage-20240116105619515

  1. 功能:返回指向vector第一个元素反向迭代器
  2. 参数:反向迭代器函数的参数为空
  3. 返回值:如果容器是只读的,返回一个只读的反向迭代器;如果容器可读可写,返回一个可读可写的反向迭代器。

demo:

// vector::rbegin/rend
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector (5);  // 5 default-constructed ints

  std::vector<int>::reverse_iterator rit = myvector.rbegin();

  int i=0;
  for (rit = myvector.rbegin(); rit!= myvector.rend(); ++rit)
    *rit = ++i;

  std::cout << "myvector contains:";
  for (std::vector<int>::iterator it = myvector.begin(); it != myvector.end(); ++it)
    std::cout << ' ' << *it;		//5  4  3  2  1
  std::cout << '\n';

  return 0;
}

容量相关函数

size

sizeimage-20240116105944519

  1. 功能:返回vector有效数据个数
  2. 参数:空
  3. 返回值:类型为size_type,等同于size_t

demo:

// vector::size

#include <iostream>

#include <vector>

int main ()
{
  std::vector<int> myints;
  std::cout << "0. size: " << myints.size() << '\n';

  for (int i=0; i<10; i++) myints.push_back(i);
  std::cout << "1. size: " << myints.size() << '\n';

  myints.insert (myints.end(),10,100);
  std::cout << "2. size: " << myints.size() << '\n';

  myints.pop_back();
  std::cout << "3. size: " << myints.size() << '\n';

  return 0;
}

output:

0. size: 0
1. size: 10
2. size: 20
3. size: 19

resize

resizeimage-20240116112034879

  1. 功能:改变vector的有效元素个数
    • 如果n<size,有效元素为前n个,删除超出的元素(是否会异地缩容取决编译器)
    • 如果n>capacity,先扩容使capacity==n,再用val填充剩下的空间
    • 如果size<n<capacity,直接用val填充capacity-size个空间
  2. 参数:
    • n:更新后vector有效元素个数
    • val:填充值
  3. 返回值:无

demo:

// resizing vector
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;

  // set some initial content:
  for (int i=1;i<10;i++) myvector.push_back(i);

  myvector.resize(5);
  myvector.resize(8,100);
  myvector.resize(12);

  std::cout << "myvector contains:";
  for (int i=0;i<myvector.size();i++)
    std::cout << ' ' << myvector[i];
  std::cout << '\n';

  return 0;
}

output:

myvector contains: 1 2 3 4 5 100 100 100 0 0 0 0 

capacity

capacityimage-20240116115903209

  1. 功能:返回vector的容量(最大存储有效元素的个数)
  2. 参数:空
  3. 返回值:size_t类型

demo:

// comparing size, capacity and max_size
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;

  // set some content in the vector:
  for (int i=0; i<100; i++) myvector.push_back(i);

  std::cout << "size: " << (int) myvector.size() << '\n';
  std::cout << "capacity: " << (int) myvector.capacity() << '\n';
  std::cout << "max_size: " << (int) myvector.max_size() << '\n';
  return 0;
}

output:

size: 100
capacity: 128
max_size: 1073741823

empty

emptyimage-20240116120331092

  1. 功能:判断vector是否为空(有效数据个数为0)
  2. 参数:无
  3. 返回值:size==0返回ture ,否则返回 false

demo:

// vector::empty
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;
  int sum (0);

  for (int i=1;i<=10;i++) myvector.push_back(i);

  while (!myvector.empty())
  {
     sum += myvector.back();
     myvector.pop_back();
  }

  std::cout << "total: " << sum << '\n';

  return 0;
}

output:

total = 55;

reserve

reserveimage-20240116120715351

  1. 功能:改变vectorcapacity,使得capacity最少容纳n个数据
    • n>capacity时,扩容至capacity==n,将原空间数据挪动到扩容后的新空间。
    • n<capacity时,不做处理。
    • reserve不会影响size
  2. 参数:vector最小的容量,实际capacity可能会大于n,类型为size_t
  3. 返回值:无

demo:

// vector::reserve
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int>::size_type sz;

  std::vector<int> foo;
  sz = foo.capacity();
  std::cout << "making foo grow:\n";
  for (int i=0; i<100; ++i) {
    foo.push_back(i);
    if (sz!=foo.capacity()) {
      sz = foo.capacity();
      std::cout << "capacity changed: " << sz << '\n';
    }
  }

  std::vector<int> bar;
  sz = bar.capacity();
  bar.reserve(100);   // this is the only difference with foo above
  std::cout << "making bar grow:\n";
  for (int i=0; i<100; ++i) {
    bar.push_back(i);
    if (sz!=bar.capacity()) {
      sz = bar.capacity();
      std::cout << "capacity changed: " << sz << '\n';
    }
  }
  return 0;
}

output:

making foo grow:
capacity changed: 1
capacity changed: 2
capacity changed: 4
capacity changed: 8
capacity changed: 16
capacity changed: 32
capacity changed: 64
capacity changed: 128
making bar grow:
capacity changed: 100

可以看见,如果提前reserve一段空间,可以减少扩容和数据拷贝的次数从而提高效率。

注意:
不同的编译器对vector扩容机制不同,在VS下扩容后是扩容前空间的1.5倍,g++下是2倍image-20240117093007188

shrink_to_fit

shrink_to_fitimage-20240117093407523

  1. 功能:减少容器的capacity以适应其尺寸,函数可能会realloc,但是对size无影响。
  2. 参数:无
  3. 返回值:无
  4. 注意:该函数没有约束力,容器可以进行自由的优化,使其capacity>size

demo:

// vector::shrink_to_fit
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector (100);
  std::cout << "1. capacity of myvector: " << myvector.capacity() << '\n';

  myvector.resize(10);
  std::cout << "2. capacity of myvector: " << myvector.capacity() << '\n';

  myvector.shrink_to_fit();
  std::cout << "3. capacity of myvector: " << myvector.capacity() << '\n';

  return 0;
}

output:

1. capacity of myvector: 100
2. capacity of myvector: 100
3. capacity of myvector: 10

获取元素

operator[]

operator[]image-20240117095306769

  1. 功能:返回vector中第n个元素的引用。与vector::at具有相同功能,不同的是 vector::at 进行了边界检查,并通过抛出 out_of_range 异常来指示请求的位置是否超出范围。
  2. 参数:n是容器中第n个元素,类型为size_t
  3. 返回值:第n个元素的引用,如果是const vector,返回常引用,否则返回引用

demo:

// vector::operator[]
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector (10);   // 10 zero-initialized elements

  std::vector<int>::size_type sz = myvector.size();

  // assign some values:
  for (unsigned i=0; i<sz; i++) myvector[i]=i;

  // reverse vector using operator[]:
  for (unsigned i=0; i<sz/2; i++)
  {
    int temp;
    temp = myvector[sz-1-i];
    myvector[sz-1-i]=myvector[i];
    myvector[i]=temp;
  }

  std::cout << "myvector contains:";
  for (unsigned i=0; i<sz; i++)
    std::cout << ' ' << myvector[i];
  std::cout << '\n';

  return 0;
}

output:

myvector contains: 9 8 7 6 5 4 3 2 1 0

data

data外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 功能:返回一个指向vector用于内部存储数据的数组的指针。因为vector数据是连续存储的,所以可以通过data偏移量访问vector中的数据,例如v.data()[1]==v[1]
  2. 参数:空
  3. 返回值:指向第一个数据的指针。如果vector只读,指针指向的类型是const_value_type,否则指针指向的类型是value_type

demo:

// vector::data
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector (5);

  int* p = myvector.data();

  *p = 10;
  ++p;
  *p = 20;
  p[2] = 100;

  std::cout << "myvector contains:";
  for (unsigned i=0; i<myvector.size(); ++i)
    std::cout << ' ' << myvector[i];
  std::cout << '\n';

  return 0;
}

output:

myvector contains: 10 20 0 100 0

修改

assign

assign外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 功能:用数据覆盖vector原本的内容,并合适地修改size。当且仅当新的容器大小大于当前vector时,数组会realloc
  2. 参数:
    • 范围分配:firstlast是其他容器的迭代器,first是序列的初始位置,last是序列的结束位置,将[first,last)中的值分配给vector,这些值包括first不包括last
    • 填充分配:nvectorsize大小,类型为size_t,用nval填充vector
  3. 返回值:空

demo:

// vector assign
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> first;
  std::vector<int> second;
  std::vector<int> third;

  first.assign (7,100);             // 7 ints with a value of 100

  std::vector<int>::iterator it;
  it=first.begin()+1;

  second.assign (it,first.end()-1); // the 5 central values of first

  int myints[] = {1776,7,4};
  third.assign (myints,myints+3);   // assigning from array.

  std::cout << "Size of first: " << int (first.size()) << '\n';
  std::cout << "Size of second: " << int (second.size()) << '\n';
  std::cout << "Size of third: " << int (third.size()) << '\n';
  return 0;
}

output:

Size of first: 7
Size of second: 5
Size of third: 3

push_back

push_back外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 功能:将val值插入到vector尾部。尾插后size会增加1个大小,当且仅当增加后的size>capacity时,分配的存储空间会realloc
  2. 参数:要复制到尾部的值,是一个常引用
  3. 返回值:空
  4. 注意:
    • 如果发生了realloc,那么realloc的时间与vectorsize成线性函数。
    • 如果发生了realloc,那么所有的迭代器,指针,引用都会失效,否则只有end_iterator是失效的,其他的迭代器,指针引用都和调用前指向相同。
    • 如果发生了realloc,所有的元素都会被复制到新分配的空间中。

demo:

// vector::push_back
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;
  int myint;

  std::cout << "Please enter some integers (enter 0 to end):\n";

  do {
    std::cin >> myint;
    myvector.push_back (myint);
  } while (myint);

  std::cout << "myvector stores " << int(myvector.size()) << " numbers.\n";

  return 0;
}

pop_back

pop_back外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 功能:删除vector中最后一个元素,size大小减一。
  2. 参数:空
  3. 返回值:空
  4. 注意:
    • pop_back后,任何指向被删除元素的迭代器,指针,引用都失效

demo:

// vector::pop_back
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;
  int sum (0);
  myvector.push_back (100);
  myvector.push_back (200);
  myvector.push_back (300);

  while (!myvector.empty())
  {
    sum+=myvector.back();
    myvector.pop_back();
  }

  std::cout << "The elements of myvector add up to " << sum << '\n';

  return 0;
}

output:

The elements of myvector add up to 600

insert

insertimage-20240117111954131

  1. 功能:通过在指定位置的元素之前插入新元素来扩展vector,从而通过插入元素的数量有效地增加容器大小。当新的size>capacity时,分配的空间会realloc

  2. 参数:

    • position:插入元素的位置,iterator是一个成员类型,定义为指向元素的random_access_iterator类型。
    • val:插入值的常引用
    • n:插入元素的个数,类型为size_t
    • first,last:指定添加元素范围的区间。 [first,last) 范围内的元素副本将插入到position位置(以相同的顺序)。范围包括first不包括lastfirstlast都是vector::iterator类型。
  3. 返回值:返回一个指向新插入的第一个元素迭代器,返回值类型为vector::iterator

  4. 注意:

    • 时间复杂度:与插入的元素数量(复制/移动构造)加上位置后的元素数量(移动)成线性关系。若不是在vector末尾插入元素,效率通常不会很高 O ( n ) O(n) O(n)

    • 迭代器失效:如果内存分配发生realloc,那么所有的迭代器,指针,引用都会失效;否则只有指向position之后的迭代器,指针,引用会失效,指向position之前的迭代器,指针,引用不会失效。

demo:

// inserting into a vector
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector (3,100);
  std::vector<int>::iterator it;

  it = myvector.begin();
  it = myvector.insert ( it , 200 );

  myvector.insert (it,2,300);

  //After reallocation, "it" no longer valid, get a new one:
  it = myvector.begin();

  std::vector<int> anothervector (2,400);
  myvector.insert (it+2,anothervector.begin(),anothervector.end());

  int myarray [] = { 501,502,503 };
  myvector.insert (myvector.begin(), myarray, myarray+3);

  std::cout << "myvector contains:";
  for (it=myvector.begin(); it<myvector.end(); it++)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

output:

myvector contains: 501 502 503 300 300 400 400 200 100 100 100

erase

erase外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 功能:从vector中删除单个元素或删除一段迭代器区间。size大小减一。
  2. 参数:
    • position:指向vector中需要被删除的元素。vector::iteratorvector::const_iterator都是成员类型,也是random_access_iterator
    • first,last:指定要删除vector的区间,包括[first,last)中的所有元素,即包括first不包括lastfirstlast都是vector::iterator类型,即random_access_iterator
  3. 返回值:返回一个指向最后一个被删除元素的下一个新位置的迭代器。
  4. 注意:
    • 时间复杂度:与删除(破坏)的元素数量加上最后一个元素删除(移动)之后的元素数量成线性关系。处尾删外,删除效率不是很高 O ( n ) O(n) O(n)
    • 迭代器失效:指向 position(或 first)及以后元素的迭代器、指针和引用将失效,而指向 position(或 first)之前元素的所有迭代器、指针和引用将保证继续指向调用前所指向的相同元素。

demo:

/ erasing from vector
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;

  // set some values (from 1 to 10)
  for (int i=1; i<=10; i++) myvector.push_back(i);

  // erase the 6th element
  myvector.erase (myvector.begin()+5);

  // erase the first 3 elements:
  myvector.erase (myvector.begin(),myvector.begin()+3);

  std::cout << "myvector contains:";
  for (unsigned i=0; i<myvector.size(); ++i)
    std::cout << ' ' << myvector[i];
  std::cout << '\n';

  return 0;
}

output:

myvector contains: 4 5 7 8 9 10

swap

swap外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 功能:用另一个vector的内容交换当前vector的内容,两个vector的类型相同,size可能不同
  2. 参数:需要交换内容的vector引用xx与当前vector具有相同类型。
  3. 返回值:空
  4. 注意:
    • 成员函数swap是通过非成员库函数swap实现的
    • vector bool 特化为此函数提供了额外的重载vector<bool>::swap

demo:

// swap vectors
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> foo (3,100);   // three ints with a value of 100
  std::vector<int> bar (5,200);   // five ints with a value of 200

  foo.swap(bar);

  std::cout << "foo contains:";
  for (unsigned i=0; i<foo.size(); i++)
    std::cout << ' ' << foo[i];
  std::cout << '\n';

  std::cout << "bar contains:";
  for (unsigned i=0; i<bar.size(); i++)
    std::cout << ' ' << bar[i];
  std::cout << '\n';

  return 0;
}

output:

foo contains: 200 200 200 200 200 
bar contains: 100 100 100 

clear

(clear)[https://cplusplus.com/reference/vector/vector/clear/]image-20240117205312205

  1. 功能:移除vector中的所有元素,让size=0。
  2. 参数:空
  3. 返回值:空
  4. 注意:
    • 调用该函数不能保证会发生realloc,也不能保证capacity会改变。强制清空capacity可以通过使用swap函数vector<T>().swap(x)
    • 复杂度:和size大小线性相关
    • 迭代器失效:vector中的所有迭代器都失效

demo:

// clearing vectors
#include <iostream>
#include <vector>

int main ()
{
  std::vector<int> myvector;
  myvector.push_back (100);
  myvector.push_back (200);
  myvector.push_back (300);

  std::cout << "myvector contains:";
  for (unsigned i=0; i<myvector.size(); i++)
    std::cout << ' ' << myvector[i];
  std::cout << '\n';

  myvector.clear();
  myvector.push_back (1101);
  myvector.push_back (2202);

  std::cout << "myvector contains:";
  for (unsigned i=0; i<myvector.size(); i++)
    std::cout << ' ' << myvector[i];
  std::cout << '\n';

  return 0;
}

output:

myvector contains: 100 200 300
myvector contains: 1101 2202

vector的实现

成员变量

T* _start:指向存储空间的起始位置

T* _finish:指向最后一个有效数据的下一个位置

T* _end_of_storage:指向最后一个有效存储空间的下一个位置

迭代器

iterator:T*的重定义。

const_iterator:const T*的重定义。

成员函数

构造/析构函数

注意:

  • 在执行拷贝构造函数时,需要考虑深拷贝的问题~
  • range构造函数中first和last的类型是一样的,所以我们调用vector<int>(10,1)时,我们想用10个1去构造,但是编译器可能会识别为10和1全部都是迭代器,此时解引用就会造成非法访问,解决办法就是在fill构造函数中将第一个参数类型指定为int ,这样编译器在模板参数和显示参数中选择调用带有显示参数的构造函数,也就是我们想要的fill构造函数。
	template<typename T>
	class vector
	{
	public:
		typedef T* iterator;
		typedef const T* const_iterator;
		vector()			//default构造函数
		{
			_start = _finish = _end_of_storage = nullptr;
		}
		vector(int sz, const T& val = T())
		{					//fill构造函数,sz的类型为int让编译器区分构造vector<int>(3,1)类型时调用的是fill构造而不是range构造
							//为vector申请sz个空间
			_finish = _start = new T[sz];
							//fill构造时,_end_of_storage和_finish指向同个位置
			_end_of_storage = _start + sz;
							//这里也可以*_finish++ = val;
			for (size_t i = 0; i < sz; i++)
			{
				push_back(val);
			}
		}
		vector(const vector<T>& v)
		{					//拷贝构造函数
							//v的size
			int sz = v._finish - v._start;
							//v的capacity
			int capacity = v._end_of_storage - v._start;
			_start = new T[capacity];
							//注意:这里依次让v的每个元素赋值给*this,当*this类似于string类型时赋值可以调用string的深拷贝
							//不能简单的使用memcpy,memcpy是浅拷贝
			for (size_t i = 0; i < sz; i++)
			{
				_start[i] = v._start[i];
			}
							//更新_finish和_end_of_storage
			_finish = _start + sz;
			_end_of_storage = _start + capacity;
		}
							//range构造函数
		template<typename InputerIterator>
		vector(InputerIterator first, InputerIterator last)
		{					
							//数据区间为[first,last)
			while (first != last)
			{				//等效于*_finish++ = *first++;
				push_back(*first++);
				//first++;
			}
		}
		~vector()
		{					//new的空间delete,防止MemoryLeak
			delete[] _start;
			_start = _finish = _end_of_storage = nullptr;
		}

测试结果:外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

赋值重载

注意:当vector类型为string等,考虑深拷贝问题

		//赋值重载函数
		vector<T>& operator=(const vector<T>& v)
		{
			int sz = v._finish - v._start;
			int capacity = v._end_of_storage - v._start;
							//start指向sz个空间
			_start = new T[sz];
			for (size_t i = 0; i < sz; i++)
			{				//使用赋值考虑深拷贝的问题
				*_finish++ = v[i];
			}
							//更新_end_of_storage
			_end_of_storage = _start + capacity;
			return *this;
		}

测试结果:image-20240118094731283

迭代器

		//迭代器
		iterator begin()
		{					
			return _start;	
		}
		const_iterator begin() const
		{
			return _start;	
		}
		
		iterator end()
		{
			return _finish;
		}
		const_iterator end() const
		{
			return _finish;
		}

测试结果:image-20240118100044157

容量相关函数

注意:

  • 实现扩容相关函数时,涉及到将原空间数据拷贝到新空间中,所以需要考虑深拷贝问题
		rsize_t capacity() const
		{
			return _end_of_storage - _start;	//_end_of_storage和_start之间是存储空间
		}
		
		rsize_t size() const
		{
			return _finish - _start;			//_finish和_start之间是有效元素
		}

		
		void reserve(size_t n)		//预先开辟n个空间
		{
			size_t cap = capacity();
			size_t sz = size();
			if (n > cap)			//当且仅当n大于当前容量扩容
			{
				T* tmp = new T[n];
										//拷贝元数据到新空间,数据拷贝时需要注意深拷贝问题,使用赋值而不用memcpy
				for (size_t i = 0; i < sz; i++)
				{
					tmp[i] = _start[i];
				}
				delete[] _start;		//释放原数据空间
										//更新_start _finish _end_of_storage
				_start = tmp;
				_finish = _start + sz;
				_end_of_storage = _start + cap;
			}
		}

		void resize(size_t sz, T val = T())
		{
			size_t _sz = _finish - _start;
			size_t _capacity = _end_of_storage - _start;
							
			if (sz < _sz)				//情况1.sz小于当前size,直接缩小当前size,capacity不变
			{
				_finish -= sz;
			}
			else if (sz <= _capacity)	//情况2.size<sz<capacity,直接在剩下的存储空间中插入capacity-
			{
				while (_sz < sz)
				{
					push_back(val);
					_sz++;
				}
			}
			else						//情况3.sz>capacity,先扩容,在插入sz-size个val
			{
				reserve(sz);
				while (_sz < sz)
				{
					push_back(val);
				}
			}
		}

测试结果:image-20240118113057550

获取元素/修改

注意:

  • 当使用insert和erase时,需要注意迭代器失效。
    • insert:若插入后扩容了,如果是异地扩容,则原来的迭代器全部失效,需要更新,若没有扩容,原本指向插入位置之后的迭代器失效,之前的没有影响
    • erase:删除位置后面的迭代器全部失效,前面的没有影响
			/*访问*/

		T& operator[](size_t pos)
		{
			assert(0 <= pos && pos < _finish - _start);
			return *(_start + pos);
		}
		const T& operator[](size_t pos) const
		{
			assert(0 <= pos && pos < _finish - _start);
			return *(_start + pos);
		}

		T front()
		{
			return *_start;
		}
		const T front() const 
		{
			return *_start;
		}

		T back()
		{
			return *_finish;
		}
		const T back() const
		{
			return *_finish;
		}


		/*修改类*/

		void push_back(const T& val)
		{
			size_t sz = _finish - _start;
			size_t ca = _end_of_storage - _start;
			if (ca == sz)
			{
				reserve(ca == 0 ? 4 : 2 * ca);
			}
			*_finish = val;
			_finish++;
			//insert(end(), val);
		}

		void pop_back()
		{
			assert(_finish - _start >= 1);
			_finish--;
			//erase(end() - 1);
		}

		iterator insert(iterator pos, const T& val)//返回值用于更新扩容前指向pos处的迭代器
		{
			int sz = _finish - _start;
			int capacity = _end_of_storage - _start;
			int gap = pos - _start;				   //记录扩容前_start和pos的相对位置
			if (_finish == _end_of_storage)		   //扩容
			{
												   //2倍扩容
				reserve(capacity == 0 ? 4 : 2*capacity);
				//此时_start _finish _end_of_storage已经是扩容后的位置了									
				pos = _start + gap;//修正pos
			}
			/*挪动数据*/
			iterator end = _finish;
			while (end > pos)
			{
				*end = *(end - 1);
				end--;
			}
			*pos = val;
			_finish++;
			return pos;
		}
		template<class Inputiterator>
		iterator insert(iterator pos, Inputiterator first, Inputiterator last)
		{
			int num = last - first;						//要插入的个数
			int sz = _finish - _start;
			int capacity = _end_of_storage - _start;
			int gap = pos - _start;						//_start和pos的相对位置
			//当前容量不够插入需要扩容
			if (sz + num >  capacity)
			{
				reserve(sz + num);
				_finish = _end_of_storage;
				pos = _start + gap;
				iterator after = pos + num;
				iterator before = pos;
				while (after < _end_of_storage)
				{
					*after++ = *before++;
				}
				while (first < last)
				{
					*pos++ = *first++;
				}
				_finish = _end_of_storage;
			}
			//当前容量够插入
			else
			{
				iterator after = pos + num;
				iterator before = pos;
				while (before < _finish)
				{
					*after++ = *before++;
				}
				while (first < last)
				{
					*pos++ = *first++;
				}
				_finish = after;
			}
			return pos;
		}

		iterator erase(iterator pos)
		{
			assert(pos >= _start);		//删除元素位置介于[first,last)
			assert(pos < _finish);
			iterator begin = pos;		//pos后面的元素往前挪
			while (begin < _finish - 1)
			{
				*begin = *(begin + 1);
				begin++;
			}
			_finish--;
			return pos;
		}

		void swap(vector<T>& v)
		{
			std::swap(_start, v._start);
			std::swap(_finish, v._finish);
			std::swap(_end_of_storage, v._end_of_storage);
		}

		void clear()
		{
			_finish = _start;			//size=0
		}

测试结果:image-20240118120643463

文章来源:https://blog.csdn.net/m0_74278159/article/details/135758174
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。