STL vector

1. 概念
vector是一种序列式容器,所谓序列式容器,即其中的元素可以排序,但是并未排序。可以把vector可作为加强版的array,它和array一样,存储空间是一段连续的内存,因此支持随机访问,但是,和array相比,vector支持动态增加数据。
vector支持动态增加数据,同时又需要保持空间的连续性从而支持随机访问,因此,在对vector动态增加元素时,如果旧有空间装满,需要申请更大的内存,并且需要把旧有数据搬到新内存去,因此,数据的搬移效率使我们在开发过程中需要考虑的重要因素。

2. API
vector提供了很多接口,以下列出vector的成员函数和操作:

(constructor) Construct vector (public member function)
(destructor) Vector destructor (public member function)
operator= Copy vector content (public member function )

Iterators:
begin Return iterator to beginning (public member type)
end Return iterator to end (public member function)
rbegin Return reverse iterator to reverse beginning (public member function)
rend Return reverse iterator to reverse end (public member function)

Capacity:
size Return size (public member function)
max_size Return maximum size (public member function)
resize Change size (public member function)
capacity Return size of allocated storage capacity (public member function)
empty Test whether vector is empty (public member function)
reserve Request a change in capacity (public member function)

Element access:
operator[] Access element (public member function)
at Access element (public member function)
front Access first element (public member function)
back Access last element (public member function)

Modifiers:
assign Assign vector content (public member function)
push_back Add element at the end (public member function)
pop_back Delete last element (public member function)
insert Insert elements (public member function)
erase Erase elements (public member function)
swap Swap content (public member function)
clear Clear content (public member function)

Allocator:
get_allocator Get allocator (public member function )

3. Vecotr内存分配
vector内存分配原则是保证一块连续的空间。
vector 并不是随每一个元素的插入而增长自己,而是当vector 需要增长自身时,它实际分配的空间比当前所需的空间要多一些,这主要是基于效率的考虑。 vector内存分配策略的实现是常常是双倍分配(不是所有),比如说当size为4,capacity大小为4,如果再push一个元素,则size为5,capacity为8。

vector在进行增数据操作时有可能会重新分配内存以保证空间的连续性。增数据操作:push_back,insert
vector在进行删数据操作时,内存不会重新分配。删数据操作:erase,pop_back

有两个概念需要明确:size和capacity
vector::size(): Returnsthe number of elementsin the vector container.
vector::capacity(): Returns the size of theallocated storage space for the elementsof the
vectorcontainer
size是元素个数,capacity则是指为vector分配的内存大小,显然,capacity一定要大于等于size。


4. reserve和resize的区别

reserve会预留内存,但不会创建元素;resize则会创建元素,在空间不足的时候,会申请内存。具体的区别,上代码:

//查看vector:size、capacity void print(vector<int> &vector) { cout << endl; cout << "my vector size:" << vector.size() << endl; cout << "my vector capacity:" << vector.capacity() << endl; } int _tmain(int argc, _TCHAR* argv[]) { vector<int> myvector1; myvector1.reserve(100); print(myvector1); vector<int> myvector2; myvector2.resize(100); print(myvector2); return 0; }

输出:
my vector size:0
my vector capacity:100

my vector size:100
my vector capacity:100



5. Vector使用示例

代码如下:

//插入4个元素 void push4element(vector<int> &vector) { vector.push_back (100); vector.push_back (100); vector.push_back (100); vector.push_back (100); } //查看vector:size、capacity void print(vector<int> &vector) { cout << endl; cout << "my vector size:" << vector.size() << endl; cout << "my vector capacity:" << vector.capacity() << endl; } int _tmain(int argc, _TCHAR* argv[]) { //初始化vector vector<int> myvector; //插入数据、查看大小 push4element(myvector); print(myvector); //插入数据、查看大小 push4element(myvector); print(myvector); //插入数据、查看大小 push4element(myvector); print(myvector); //插入数据、查看大小 push4element(myvector); print(myvector); //清空vector while (!myvector.empty()) { myvector.pop_back(); } print(myvector); //重置vector大小 myvector.resize(myvector.size()+2); print(myvector); system("pause"); return 0; }


x32,win7,VS2010运行输出结果:
my vector size:4
my vector capacity:4

my vector size:8
my vector capacity:9

my vector size:12
my vector capacity:13

my vector size:16
my vector capacity:19

my vector size:0
my vector capacity:19

my vector size:2
my vector capacity:19


lx64 inux 2.6.9 gcc 运行输出结果:
my vector size:4
my vector capacity:4

my vector size:8
my vector capacity:8

my vector size:12
my vector capacity:16

my vector size:16
my vector capacity:16

my vector size:0
my vector capacity:16

my vector size:2
my vector capacity:16

从capacity的增长情况来看,不同库内存分配策略实现不一样,但总体上都是增量分配。

6. Vecotr使用常见问题

1)迭代器失效
iterator失效主要有两种情况:
a.iterator变量已经变成了“悬空指针”,对它进行*,++,--都会引起程序内存操作异常;
b.iterator所指向的变量已经不是你所以为的那个变量了。

vector迭代器的几种失效的情况:
a.当插入(push_back)一个元素后,end操作返回的迭代器肯定失效。
b.当插入(push_back)一个元素后,capacity返回值与没有插入元素之前相比有改变,则需要重新加载整个容器,此时first和end操作返回的迭代器都会失效。
c.当进行删除操作(erase,pop_back)后,指向删除点的迭代器全部失效;指向删除点后面的元素的迭代器也将全部失效。

比较常见的一种场景是遍历一个vector,删除符合条件的数据,正确的写法如下:

vector<int> myvector; for(vector<int>::iterator iter=myvector.begin();iter!=myvector.end();) { if(10 == (*iter)) iter=myvector.erase(iter); else ++iter; }

在erase之后,删除的迭代器之后的数据前移,因此,在删除之后,不需要对迭代器++

2)元素访问
vector支持随机内存访问,我们可以使用at和[]来访问元素,这两者有什么区别呢?
在不越界的情况下,两者没有区别;在越界的情况下,at会抛出一个std::out_of_range异常。而C++98标准说[]可以、但不一定要进行下标越界检查。因此,标准库实现方可以自由选择是否为operator[]加上下标越界检查功能。上代码

at:

vector<int> myvector; myvector.reserve(10); try { cout << myvector.at(100); } catch(...) { cout << "got you" << endl; }

VS2010输出:
got you

[]:

vector<int> myvector; myvector.reserve(10); try { cout << myvector[100]; } catch(...) { cout << "got you" << endl; }

VS2010:
程序崩溃

vector在调用erase,pop_back删除元素的时候,并不会释放内存,因此,在vector生命期内,需要释放vector所占用内存的时候,可以使用如下代码:

template < class T > void ClearVector( vector< T >& vt ) { vector< T > vtTemp; veTemp.swap( vt ); }

如果需要部分释放,可以先将vector的数据拷贝到另一个vector,然后调用swap。

vector具有很多优秀的特点:随机访问、动态扩张、额外消耗少,非常适合多查询的应用场景。但是,由于其需要保持内存连续,在删除某个元素之后,后续元素需要拷贝前移,这会带来一些消耗,因此不适合随机删除的场景。

### C++ STL Vector 的使用方法及示例 #### 1. 基本概念 `std::vector` 是 C++ 标准模板库(STL)中的一个重要组件,属于一种动态数组容器。与传统静态数组相比,`std::vector` 可以在运行时动态调整其大小[^3]。 为了使用 `std::vector`,需要包含头文件 `<vector>` 并显式实例化模板类[^2]。 #### 2. 创建和初始化 以下是创建并初始化 `std::vector` 的几种常见方式: ```cpp #include <iostream> #include <vector> int main() { // 方式一:默认构造函数 std::vector<int> v1; // 方式二:指定初始容量 std::vector<int> v2(5); // 初始化为五个0 // 方式三:指定初始值 std::vector<int> v3(5, 10); // 初始化为五个10 // 方式四:通过另一个向量初始化 std::vector<int> v4(v3); // 方式五:从数组初始化 int arr[] = {1, 2, 3}; std::vector<int> v5(arr, arr + sizeof(arr)/sizeof(int)); return 0; } ``` #### 3. 遍历元素 可以通过迭代器或者范围循环来遍历 `std::vector` 中的元素[^1]。 ```cpp #include <iostream> #include <vector> int main() { std::vector<int> vec = {1, 2, 3, 4, 5}; // 方法一:使用迭代器 for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) { std::cout << *it << " "; } std::cout << std::endl; // 方法二:使用范围for循环 for (const auto& elem : vec) { std::cout << elem << " "; } return 0; } ``` #### 4. 动态调整大小 `std::vector` 支持动态扩展和收缩,常用的方法有 `push_back()`、`pop_back()`、`resize()` 和 `reserve()`[^4][^5]。 - **`push_back(value)`**: 向向量末尾添加新元素。 - **`pop_back()`**: 删除向量最后一个元素。 - **`resize(new_size)`**: 调整向量大小至 `new_size`。 - **`reserve(size)`**: 预留至少 `size` 大小的空间。 示例如下: ```cpp #include <iostream> #include <vector> int main() { std::vector<int> vec; // 添加元素 vec.push_back(1); vec.push_back(2); // 扩展大小 vec.resize(5, 0); // 将vec扩展到5个元素,默认填充为0 // 预留空间 vec.reserve(10); // 至少预留10个位置 // 移除最后元素 vec.pop_back(); for (const auto& elem : vec) { std::cout << elem << " "; } return 0; } ``` #### 5. 访问元素 可以使用索引运算符 `[ ]` 或者成员函数 `at(index)` 来访问向量中的元素。 ```cpp #include <iostream> #include <vector> int main() { std::vector<int> vec = {1, 2, 3, 4, 5}; // 使用 [] 运算符 std::cout << "First element: " << vec[0] << std::endl; // 使用 at() 函数 try { std::cout << "Third element: " << vec.at(2) << std::endl; } catch (const std::out_of_range& e) { std::cerr << "Error: " << e.what() << std::endl; } return 0; } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值