C++中的vector容器

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: C++中的vector容器

vector的介绍


vector是封装动态数组的顺序容器。

 就像数组一样,vector也采用的连续存储空间来存储元素。这也就意味着我们可以通过下标来获取vector的元素,和数组一样高效。但是又不像数组,vector的大小是可以动态改变的,且它的大小会被容器自动处理。

 本质上,vector使用动态分配数组来存储它的元素。当新元素插入时,这个数组需要被重新分配大小,分配一个新的数组,然后将全部元素转移到这个数组。就时间而言,是一个代价相对较高的任务,因为每当一个新的元素加入容器时,vector并不分每次都重新分配大小。

 vector空间分配策略:vector会分配一些额外的空间以适应可能的增长,因为存储空间比实际需要的存储空间更大。不同的库采用不同的策略权衡空间的使用和重新分配。但是无论如何,重新分配都应该是对数增长的间隔大小,以至于在末尾插入一个元素的时候是在常数时间的复杂度完成的。因此,vector占用了更多的存储空间,为了获得管理存储空间的能力,并且以一种有效的方式动态增长。

 与其他动态序列容器相比,vector在访问元素的时候更加高效,在末尾添加和删除元素相对高效。对于其它不在末尾的删除和插入,效率更低。


vector的使用

vector的定义

image.png

int main()
{
  vector<int> first;
  vector<int> second(4, 100);
  vector<int> third(second.begin(), second.end());
  vector<int> fourth(third);
  int myints[] = { 16, 2, 77, 29 };
  vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));
  cout << "The contents of fifth are:";
  for (vector<int>::iterator it = fifth.begin(); it != fifth.end(); ++it)
    cout << ' ' << *it;
  cout << '\n';
  return 0;
}

e1b762abbb384e00b283721f48fe3fef.png

vector初始化

image.png

int main()
{
  vector<int> v1;
  vector<string> v2;
  vector<vector<int>> v3;  //这里相当于二维数组int a[n][n];
  vector<int> v4{ 1,2,3,4,5 };
  vector<int> v5 = { 1,2,3,4,5 }; //列表初始化,注意使用的是花括号
  vector<string> v6 = { "hi","my","name","is","lee" };
  vector<int> v7(5, -1); //初始化为-1,-1,-1,-1,-1。第一个参数是数目,第二个参数是要初始化的值
  vector<string> v8(3, "hi");
  vector<int> v9(10); //默认初始化为0
  vector<int> v10(4); //默认初始化为空字符串
  return 0;
}

vector iterator的使用

image.png

int main()
{
  vector<int> myvector{ 1, 2, 3, 4, 5 };
  cout << *myvector.begin() << endl;
  cout << *(myvector.end() - 1) << endl;
  cout << *myvector.rbegin() << endl;
  cout << *(myvector.rend() - 1) << endl;
  return 0;
}

35b71f397e194cf8bc73ac42e4055f3d.png

vector空间增长问题

image.png

capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。vector具体增长多少是根据具体的需求定义的。vs是PJ版本的STL,g++是SGI版本的STL;

 reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题;

 resize在开空间的同时还会进行初始化,影响size。

int main()
{
  vector<int> myints;
  cout << "0.size:" << myints.size() << endl;
  for (int i = 0; i < 10; i++)
    myints.push_back(i);
  cout << "1.size:" << myints.size() << endl;
  myints.insert(myints.end(), 10, 100);
  cout << "2.size:" << myints.size() << endl;
  myints.pop_back();
  cout << "3.size:" << myints.size() << endl;
  return 0;
}

ed43be17f9b548fea6876b32e1f9794a.png

int main()
{
  vector<int> myvector;
  for (int i = 0; i < 100; i++)
    myvector.push_back(i);
  cout << "size:" << (int)myvector.size() << endl;
  cout << "capacity:" << (int)myvector.capacity() << endl;
  cout << "max_size:" << (int)myvector.max_size() << endl;
  return 0;
}

0a013a4fc8d54c0baa328699f389f9ac.png

int main()
{
  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();
  }
  cout << "total:" << sum << endl;
  return 0;
}

5a5da741f7584549aaaee0a4e0b9d6b0.png

int main()
{
  vector<int> myvector;
  for (int i = 1; i < 10; i++)
    myvector.push_back(i);
  cout << "0.size:" << myvector.size() << endl;
  myvector.resize(5);
  cout << "1.size:" << myvector.size() << endl;
  myvector.resize(8, 100);
  cout << "2.size:" << myvector.size() << endl;
  myvector.resize(12);
  cout << "3.size:" << myvector.size() << endl;
  cout << "myvector contains:";
  for (int i = 0; i < myvector.size(); i++)
    cout << ' ' << myvector[i];
  cout << endl;
  return 0;
}

ddb8d94a0af94cc28a3716ca038e9d1e.png

vector增删改查

image.png

int main()
{
  vector<int> myvector;
  for (int i = 1; i <= 10; i++)
    myvector.push_back(i);
  for (int i = 0; i < myvector.size(); i++)
    cout << myvector[i] << ' ';
  cout << endl;
  for (int i = 0; i < 3; i++)
    myvector.pop_back();
  for (int i = 0; i < myvector.size(); i++)
    cout << myvector[i] << ' ';
  return 0;
}

6a683a6f61c54b50ae365ec98c7a9cc1.png

int main()
{
  vector<int> v;
  v.push_back(1);
  v.push_back(2);
  v.push_back(3);
  v.push_back(4);
  for (auto e : v)
  {
    cout << e << " ";
  }
  cout << endl;
  vector<int>::iterator pos = find(v.begin(), v.end(), 2);
  if (pos != v.end())
  {
    v.insert(pos, 20);
  }
  for (auto e : v)
  {
    cout << e << " ";
  }
  cout << endl;
  pos = find(v.begin(), v.end(), 2);
  if (pos != v.end())
  {
    v.erase(pos);
  }
  for (auto e : v)
  {
    cout << e << " ";
  }
  cout << endl;
  v.erase(v.begin());
  for (auto e : v)
  {
    cout << e << " ";
  }
  cout << endl;
  return 0;
}

9a48d9d33a294cd595b87d0d6afa2778.png

int main()
{
  vector<int> myvector;
  for (int i = 1; i <= 10; i++)
    myvector.push_back(i);
  //删除指定位置数据
  myvector.erase(myvector.begin() + 5);
  //删除指定一个位置,到另一个位置间的所有数据
  myvector.erase(myvector.begin(), myvector.begin() + 3);
  cout << "myvector contains:";
  for (unsigned i = 0; i < myvector.size(); i++)
    cout << ' ' << myvector[i];
  cout << endl;
  return 0;
}

648aeb54ceba4e48abe12892153f07b1.png

int main()
{
  vector<int> foo(3, 100);
  vector<int> bar(5, 200);
  foo.swap(bar);
  cout << "foo contains:";
  for (unsigned i = 0; i < foo.size(); i++)
    cout << ' ' << foo[i];
  cout << endl;
  cout << "bar contains:";
  for (unsigned i = 0; i < bar.size(); i++)
    cout << ' ' << bar[i];
  cout << endl;
  return 0;
}

e1dd0adb47da4741a59991d298880a62.png

vector迭代器失效问题

 迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了封装。因此迭代器失效,实际就是迭代器底层对应的指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃。

对于vector可能会导致其迭代器失效的操作:

  1. 会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、push_back等;
  2. 指定位置元素的删除操作–erase;
  3. 注意:Linux下,g++编译器对迭代器失效的检测并不是非常严格,处理也没有vs下极端


目录
相关文章
|
24天前
|
存储 编译器 C语言
【c++丨STL】vector的使用
本文介绍了C++ STL中的`vector`容器,包括其基本概念、主要接口及其使用方法。`vector`是一种动态数组,能够根据需要自动调整大小,提供了丰富的操作接口,如增删查改等。文章详细解释了`vector`的构造函数、赋值运算符、容量接口、迭代器接口、元素访问接口以及一些常用的增删操作函数。最后,还展示了如何使用`vector`创建字符串数组,体现了`vector`在实际编程中的灵活性和实用性。
49 4
|
5天前
|
存储 对象存储 C++
C++ 中 std::array<int, array_size> 与 std::vector<int> 的深入对比
本文深入对比了 C++ 标准库中的 `std::array` 和 `std::vector`,从内存管理、性能、功能特性、使用场景等方面详细分析了两者的差异。`std::array` 适合固定大小的数据和高性能需求,而 `std::vector` 则提供了动态调整大小的灵活性,适用于数据量不确定或需要频繁操作的场景。选择合适的容器可以提高代码的效率和可靠性。
23 0
|
10天前
|
存储 编译器 C语言
【c++丨STL】vector模拟实现
本文深入探讨了 `vector` 的底层实现原理,并尝试模拟实现其结构及常用接口。首先介绍了 `vector` 的底层是动态顺序表,使用三个迭代器(指针)来维护数组,分别为 `start`、`finish` 和 `end_of_storage`。接着详细讲解了如何实现 `vector` 的各种构造函数、析构函数、容量接口、迭代器接口、插入和删除操作等。最后提供了完整的模拟实现代码,帮助读者更好地理解和掌握 `vector` 的实现细节。
20 0
|
28天前
|
存储 设计模式 C++
【C++】优先级队列(容器适配器)
本文介绍了C++ STL中的线性容器及其适配器,包括栈、队列和优先队列的设计与实现。详细解析了`deque`的特点和存储结构,以及如何利用`deque`实现栈、队列和优先队列。通过自定义命名空间和类模板,展示了如何模拟实现这些容器适配器,重点讲解了优先队列的内部机制,如堆的构建与维护方法。
35 0
|
2月前
|
存储 C++ 索引
【C++打怪之路Lv9】-- vector
【C++打怪之路Lv9】-- vector
26 1
|
2月前
|
编译器 C++
【C++】—— vector模拟实现
【C++】—— vector模拟实现
|
2月前
|
算法 C++ 容器
C++之打造my vector篇(下)
C++之打造my vector篇(下)
35 0
|
2月前
|
存储 编译器 C++
C++之打造my vector篇(上)
C++之打造my vector篇(上)
34 0
|
2月前
|
算法 C++ 容器
【C++】—— vector使用
【C++】—— vector使用
|
2月前
|
存储 缓存 C++
C++番外篇——list与vector的比较
C++番外篇——list与vector的比较
26 0