赞
踩
对于我们库里面的vector。被包含在一个<vector>的头文件中
vector 是 C++ 标准模板库(Standard Template Library, STL)中的一个非常重要和常用的容器。它提供了一种动态数组的实现,允许你在运行时动态地增加或减少元素的数量,同时保留元素的顺序。vector 内部通过连续的内存空间来存储元素,这意呀着它可以快速地访问任何位置的元素(通过索引),但向vector中插入或删除元素(尤其是在非末尾位置)时可能会相对较慢,因为可能需要重新分配内存并移动元素以保持连续性。
提供了一个模版和一个内存池。 模版是用来解决我们的vector里面能存的不止一种数据类型。
begin 和end 获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置 的iterator/const_iterator
rbegin和rend :获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的 reverse_iterator
基础的构造函数:
我们按照顺序依次举例:
- std::vector<int> first; // empty vector of ints
- std::vector<int> second (4,100); // four ints with value 100
- std::vector<int> third (second.begin(),second.end()); // iterating through second
- std::vector<int> fourth (third); // a copy of third
第一个是不带参数的初始化。第二个是 存四个100 的值进入数组
第三个是迭代器初始化,第四个是一个拷贝构造
一些常用的接口
size()
size这个函数 会返回我们数的大小,有多少个有效数据元素。
用法:vector<int> s ; int size=s.size();
resize:
这个函数是用来调整数组的大小的,这个时候就分几种情况了
如果 n 小于当前容器大小,则内容将减少到前 n 个元素,删除超出的元素(并销毁它们)。 如果 n 大于当前容器大小,则通过在末尾插入所需数量的元素来扩展内容,以达到 n 的大小。如果指定了 val,则新元素将被初始化为 val 的副本,否则,它们将被值初始化。 如果 n 也大于当前容器容量,则会自动重新分配已分配的存储空间。 请注意,此函数通过插入或删除容器中的元素来更改容器的实际内容。
用法:
- #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;
- }
capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。 这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义 的。vs是PJ版本STL,g++是SGI版本STL。
- #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;
- }
判断是否是是空。
用法:
- #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;
- }
push_back
这个接口的功能是在vector的末尾插入我们的新元素,尾插的功能。
例子:
- #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
是将我们的vector的末尾的元素弹出,尾删的功能。
用法:
- #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;
- }
pop_back和push_back 是这两个接口的功能相对,对我们的数据进行出入。
reserve
reserve这个单词有存储的意思,而我们的这个就是进行空间的开辟的,我们可以提前开辟我们的数组vector的空间 。
要求vector的容量至少足以包含 n 个元素。
如果 n 大于当前的容量,该函数会导致容器重新分配其存储空间,将其容量增加到 n(或更大)。 在所有其他情况下,函数调用不会导致重新分配,并且向量容量不受影响。 此函数对向量大小没有影响,也不能改变其元素。
对于我们的n大于当前的容量时我们的这里并没有给出肯定的规定,所以对于不同平台,得到的结果是不一样的,对于 :
vs:按照1.5倍方式扩容。
linux:按照2倍方式扩容。
shrink_to_fit
是进行缩容,将我们的容量转换成我们的n,
该请求是不具有约束力的,并且容器实现可以自由地进行优化,并使向量的容量大于其大小。 这可能会导致重新分配,但对向量大小没有影响,也不能更改其元素。
shrink_to_fit是一个非强制性请求,标准库的实现可以选择忽略这个请求。
因此,在VS和Linux下,std::vector的shrink_to_fit是否实现缩容取决于具体的标准库实现和当前的内存状态。如果你需要精确控制内存使用,可能需要考虑其他数据结构或内存管理策略。
对于我们的find他不是我们的vector的成员函数,而是包含在我们的头文件《algorithm》里面;
用法:
insert和erase分别是进行我们的在指定位置插入和删除。
- // 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);
-
- // "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;
- }
- // 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;
- }
swap函数,我们的vector提供了一个交换函数,但是我们的库里面也提供了一个交换的swap函数。
vector的成员函数swap用于交换两个std::vector实例的内容。
std::swap是一个非成员函数模板,定义在头文件<algorithm>中。
区别
clear
clear()函数的作用是移除std::vector中的所有元素,这意味着这些元素会被销毁(如果有必要的话,比如它们是动态分配的对象)。
执行clear()后,std::vector的大小(即其中元素的数量)变为0,但容器本身仍然存在。
调用clear()时,并不保证std::vector的容量会发生变化。也就是说,虽然所有元素都被移除了,但std::vector仍然可能保留其原有的存储空间,以便将来添加新元素时不需要立即重新分配。
- #include <vector>
-
- int main() {
- std::vector<int> vec = {1, 2, 3, 4, 5};
-
- // 假设此时vec的容量大于其大小
-
- vec.clear(); // 移除所有元素,但容量可能不变
-
- // 使用swap技巧来减少容量
- std::vector<int>().swap(vec); // 创建一个空的vector并与其进行swap
-
- // 现在vec的大小和容量都应该是0
- }
operate[]和at
我们的vector 之所以能随机访问我们的数据元素,也是因为我们的vector它重载了我们的[]。
vector 是一种非常常用的容器,它提供了动态数组的功能。std::vector 提供了两种主要的元素访问方式:operator[] 和 at()。尽管它们都可以用来访问 vector 中的元素,但它们在错误处理和性能上存在一些关键的区别
1. operator[]
2. at()
迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对指针进行了 封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器底层对应指针所指向的 空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器, 程序可能会崩溃)。
- #include <iostream>
- using namespace std;
- #include <vector>
-
- int main()
- {
- int a[] = { 1, 2, 3, 4 };
- vector<int> v(a, a + sizeof(a) / sizeof(int));
-
- // 使用find查找3所在位置的iterator
- vector<int>::iterator pos = find(v.begin(), v.end(), 3);
-
- // 删除pos位置的数据,导致pos迭代器失效。
- v.erase(pos);
- cout << *pos << endl; // 此处会导致非法访问
- return 0;
- }
erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代 器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是 没有元素的,那么pos就失效了。因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效 了。
:
- #include <iostream>
- using namespace std;
- #include <vector>
-
- int main()
- {
- vector<int> v{1,2,3,4,5,6};
-
- auto it = v.begin();
-
- // 将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容
- // v.resize(100, 8);
-
- // reserve的作用就是改变扩容大小但不改变有效元素个数,操作期间可能会引起底层容量改变
- // v.reserve(100);
-
- // 插入元素期间,可能会引起扩容,而导致原空间被释放
- // v.insert(v.begin(), 0);
- // v.push_back(8);
-
- // 给vector重新赋值,可能会引起底层容量改变
- v.assign(100, 8);
-
- /*
- 出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,
- 而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的
- 空间,而引起代码运行时崩溃。
- 解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给it重新
- 赋值即可。
- */
- while(it != v.end())
- {
- cout<< *it << " " ;
- ++it;
- }
- cout<<endl;
- return 0;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。