文章目录
- C++ | C++ STL vector容器详解
- C++ STL vector容器详解
- 创建`vector`容器的几种方式
- 创建存储 `double` 类型元素的一个 `vector` 容器:
- 在创建的同时指定初始值以及元素个数:
- 在创建时指定元素个数:
- 通过存储元素类型相同的其它 `vector` 容器,也可以创建新的 `vector` 容器:
- `vector`容器包含的成员函数
- 实例1(`push_back()`、`size()`、`begin()`、`end()`、`at()`、`insert()`)
- C++ STL vector容器迭代器用法详解
- vector 支持迭代器的成员函数:
- vector容器迭代器的基本用法
- 实例2(`begin()`和`end()`)
- 实例3(`cbegin()`和`cend()`)
- 实例4(反向迭代器`rbegin()`和`rend()`)
- vector容器迭代器的独特之处
- 实例5(空的 `vector` 容器,不能使用迭代器)
- 实例6(`reserve()`)
- 实例7(迭代器重新初始化)
- C++ STL vector容器访问元素的几种方式
- 访问`vector`容器中单个元素
- 实例8(使用下标`[]`访问)
- 实例9(使用`at()`函数访问)
- 实例10(使用`front()` 和 `back()`函数)
- 访问vector容器中多个元素
- 实例11(使用size()函数)
- 实例12(基于范围的循环)
- 实例13(使用迭代器)
- C++ `vector`容量(`capacity`)和大小(`size`)的区别
- 实例13(capacity()和size()函数)
- 实例14
- 修改`vector`容器的容量和大小
- 实例15(`resize()`函数)
- `vector`容器容量和大小的数据类型
- 深度剖析C++ vector容器的底层实现机制
- `vector`扩大容量的本质
- C++ STL vector添加元素(push_back()和emplace_back())详解
- 实例16(`push_back()`函数):
- 实例17(`emplace_back()`函数)
- `emplace_back()`和`push_back()`的区别
- 实例18
- 实例19
- C++ STL `vector`插入元素(`insert()`和`emplace()`)详解
- `insert()`
- 实例20(`insert()`)
- `emplace()`
- 实例21(`emplace()成员函数`)
- 实例22(insert()和emplace()函数)
- `C++ STL vector`删除元素的几种方式(超级详细)
- 删除 `vector` 容器元素的几种方式:
- 实例23(`pop_back()`函数)
- 实例24(`erase()`函数)
- 实例25(`swap()`和`pop_back()`函数)
- 实例26(`erase(begin, end)`函数)
- 实例27(`remove()`函数)
- 实例28(remove()函数)
- 实例29(`clear()`函数)
- 如何避免`vector`容器进行不必要的扩容?
- `vector`模板类中功能类似的成员方法:
- 实例30
- 实例31
- `vector swap()`成员方法还可以这样用!
- 实例32
- 实例33
- 实例34(`shrink_to_fit()函数`)
- 利用swap()方法去除vector多余容量
- 实例35
C++ | C++ STL vector容器详解
C++ STL vector容器详解
vector
容器是 STL 中最常用的容器之一,它和 array
容器非常类似,都可以看做是对 C++ 普通数组的“升级版”。不同之处在于,array
实现的是静态数组(容量固定的数组),而 vector
实现的是一个动态数组,即可以进行元素的插入和删除,在此过程中,vector
会动态调整所占用的内存空间,整个过程无需人工干预。
vector
常被称为向量容器,因为该容器擅长在尾部插入或删除元素,在常量时间内就可以完成,时间复杂度为O(1)
;而对于在容器头部或者中部插入或删除元素,则花费时间要长一些(移动元素需要耗费时间),时间复杂度为线性阶O(n)
。
Standard library header <vector>
创建vector
容器的几种方式
创建存储 double
类型元素的一个 vector
容器:
std::vector<double> values;
注意,这是一个空的 vector
容器,因为容器中没有元素,所以没有为其分配空间。
当添加第一个元素(比如使用 push_back()
函数)时,vector
会自动分配内存。
在创建好空容器的基础上,还可以像下面这样通过调用 reserve()
成员函数来增加容器的容量:
values.reserve(20);
这样就设置了容器的内存分配,即至少可以容纳 20 个元素。
注意,如果 vector
的容量在执行此语句之前,已经大于或等于 20 个元素,那么这条语句什么也不做;
另外,调用 reserve()
不会影响已存储的元素,也不会生成任何元素,即 values
容器内此时仍然没有任何元素。
注意
:如果调用reserve()
来增加容器容量,之前创建好的任何迭代器(例如开始迭代器和结束迭代器)都可能会失效,这是因为,为了增加容器的容量,vector<T>
容器的元素可能已经被复制或移到了新的内存地址。所以后续再使用这些迭代器时,最好重新生成一下。
在创建的同时指定初始值以及元素个数:
std::vector<int> values = {1, 2, 4, 88, 99};//含有5个元素的vector容器
在创建时指定元素个数:
std::vector<int> values(20);//含有20个元素,默认初始值为0
注意:圆括号
()
和大括号{}
是有区别的,前者(例如(20)
)表示元素的个数,而后者(例如{20}
) 则表示vector
容器中只有一个元素 20。
如果不想用 0 作为默认值,也可以指定一个其它值,例如:
std::vector<int> values(20, 1);//第二个参数指定所有元素的初始值为1
int num=20;
double value =1.0;
std::vector<double> values(num, value);//两个参数可以是变量
通过存储元素类型相同的其它 vector
容器,也可以创建新的 vector
容器:
std::vector<char>value1(5, 'c');
std::vector<char>value2(value1);
由此,value2
容器中也具有 5 个字符 'c'
。
在此基础上,如果不想复制其它容器中所有的元素,可以用一对指针或者迭代器来指定初始值的范围,例如:
int array[]={1,2,3};
std::vector<int>values(array, array+2);//values 将保存{1,2}
std::vector<int>value1{1,2,3,4,5};
std::vector<int>value2(std::begin(value1),std::begin(value1)+3);//value2保存{1,2,3}
vector
容器包含的成员函数
函数成员 | 函数功能 |
| 返回指向容器中第一个元素的迭代器。 |
| 返回指向容器最后一个元素所在位置后一个位置的迭代器,通常和 |
| 返回指向最后一个元素的迭代器。 |
| 返回指向第一个元素所在位置前一个位置的迭代器。 |
| 和 |
| 和 |
| 和 |
| 和 |
| 返回实际元素个数。 |
| 返回元素个数的最大值。这通常是一个很大的值,一般是 232-1,所以我们很少会用到这个函数。 |
| 改变实际元素的个数。 |
| 返回当前容量。 |
| 判断容器中是否有元素,若无元素,则返回 |
| 增加容器的容量。 |
| 将内存减少到等于当前元素实际所使用的大小。 |
| 重载了 |
| 使用经过边界检查的索引访问元素。 |
| 返回第一个元素的引用。 |
| 返回最后一个元素的引用。 |
| 返回指向容器中第一个元素的指针。 |
| 用新元素替换原有内容。 |
| 在序列的尾部添加一个元素。 |
| 移出序列尾部的元素。 |
| 在指定的位置插入一个或多个元素。 |
| 移出一个元素或一段元素。 |
| 移出所有的元素,容器大小变为 0。 |
| 交换两个容器的所有元素。 |
| 在指定的位置直接生成一个元素。 |
| 在序列尾部生成一个元素。 |
C++ 11 标准库还新增加了 begin()
和 end()
这 2 个函数,和 vector
容器包含的 begin()
和 end()
成员函数不同,标准库提供的这 2 个函数的操作对象,既可以是容器,还可以是普通数组。当操作对象是容器时,它和容器包含的 begin()
和 end()
成员函数的功能完全相同;如果操作对象是普通数组
,则 begin()
函数返回的是指向数组第一个元素的指针,同样 end()
返回指向数组中最后一个元素之后一个位置的指针(注意不是最后一个元素)。
vector
容器还有一个 std::swap(x , y)
非成员函数(其中 x
和 y
是存储相同类型元素的 vector
容器),它和 swap()
成员函数的功能完全相同,仅使用语法上有差异。
实例1(push_back()
、size()
、begin()
、end()
、at()
、insert()
)
/*******************************************************************
* > File Name: stl-vector.cpp
* > Create Time: 2021年10月10日 12:44:11
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<char> value; // 初始化一个空的vector容器
value.push_back('S');// 添加元素'S'
value.push_back('T');// 添加元素'T'
value.push_back('L');// 添加元素'L'
printf("元素个数:%ld\n", value.size());// 元素的实际个数
for(auto i = value.begin(); i < value.end(); i++){
cout << *i << " " ;// 输出元素
}
cout << endl;// 换行
value.insert(value.begin(), 'C');// 在首位插入元素
cout << "首个元素:" << value.at(0) << endl;// 使用at()访问元素
return 0;
}
编译、运行:
PS D:\study\cplusplus\day15> .\stl-vector.exe
元素个数:3
S T L
首个元素:C
C++ STL vector容器迭代器用法详解
vector 支持迭代器的成员函数:
成员函数 | 功能 |
| 返回指向容器中第一个元素的正向迭代器;如果是 |
| 返回指向容器最后一个元素之后一个位置的正向迭代器;如果是 |
| 返回指向最后一个元素的反向迭代器;如果是 |
| 返回指向第一个元素之前一个位置的反向迭代器。如果是 |
| 和 |
| 和 |
| 和 |
| 和 |
C++ 11
新添加的begin()
和end()
全局函数也同样适用于vector
容器。即当操作对象为vector
容器时,其功能分别和上表 中的begin()
、end()
成员函数相同。
以上函数在实际使用时,其返回值类型都可以使用
auto
关键字代替,编译器可以自行判断出该迭代器的类型。
vector容器迭代器的基本用法
实例2(begin()
和end()
)
/*******************************************************************
* > File Name: stl-vector-begin-end.cpp
* > Create Time: 2021年11月10日 20:08:03
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>values{1, 2, 3, 4, 5};
auto first = values.begin();
auto end = values.end();
while(first != end){
cout << *first << " ";
++ first;
}
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day33> make
g++ -o stl-vector-begin-end stl-vector-begin-end.cpp -g -Wall -std=c++11
PS E:\fly-prj\cplusplus\day33> .\stl-vector-begin-end.exe
1 2 3 4 5
与此同时,还可以使用全局的 begin()
和 end()
函数来从容器中获取迭代器。
auto first = std::begin(values);
auto end = std::end(values);
cbegin()
/cend()
成员函数和 begin()
/end()
唯一不同的是,前者返回的是 const
类型的正向迭代器,这就意味着,由 cbegin()
和 cend()
成员函数返回的迭代器,可以用来遍历容器内的元素,也可以访问元素,但是不能对所存储的元素进行修改。
实例3(cbegin()
和cend()
)
//*******************************************************************
* > File Name: stl-vector-cbegin-cend.cpp
* > Create Time: 2021年11月10日 20:15:24
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>values{1 ,2 ,3 , 4 ,5};
auto first = values.cbegin();
auto end = values.cend();
while(first != end){
cout << *first << " ";//不可修改*first
++ first;
}
cout << endl;
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day33> make
g++ -o stl-vector-cbegin-cend stl-vector-cbegin-cend.cpp -g -Wall -std=c++11
PS E:\fly-prj\cplusplus\day33> .\stl-vector-cbegin-cend.exe
1 2 3 4 5
vector
模板类中还提供了 rbegin()
和 rend()
成员函数,分别表示指向最后一个元素和第一个元素前一个位置的随机访问迭代器,又称它们为反向迭代器。
实例4(反向迭代器rbegin()
和rend()
)
/*******************************************************************
* > File Name: stl-vector3.cpp
* > Create Time: 2021年10月10日 18:54:46
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[]){
vector<int> values{1, 2, 3, 4, 5};
auto first = values.rbegin();
auto end = values.rend();
while(first != end){
cout << *first << ' ';
++first;
}
cout << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day15> make stl-vector3
g++ -o stl-vector3 stl-vector3.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day15> .\stl-vector3.exe
5 4 3 2 1
vector容器迭代器的独特之处
和 array
容器不同,vector
容器可以随着存储元素的增加,自行申请更多的存储空间。
因此,在创建 vector
对象时,我们可以直接创建一个空的 vector
容器,并不会影响后续使用该容器。
但这会产生一个问题,即在初始化空的 vector
容器时,不能使用迭代器。
也就是说,如下初始化 vector
容器的方法是不行的:
实例5(空的 vector
容器,不能使用迭代器)
/*******************************************************************
* > File Name: stl-vector4.cpp
* > Create Time: 2021年10月10日 20:04:57
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> values;
int val = 1;
for(auto first = values.begin(); first < values.end(); ++first, val ++){
*first = val;// 无效
cout << *first;// 无任何输出
}
return 0;
}
编译、运行(无任何输出
):
对于空的
vector
容器来说,begin()
和end()
成员函数返回的迭代器是相等的,即它们指向的是同一个位置。
所以,对于空的
vector
容器来说,可以通过调用push_back()
或者借助resize()
成员函数实现初始化容器的目的。
vector
容器在申请更多内存的同时,容器中的所有元素可能会被复制或移动到新的内存地址,这会导致之前创建的迭代器失效。
实例6(reserve()
)
/*******************************************************************
* > File Name: stl-vector.cpp
* > Create Time: 2021年10月12日 0:43:34
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> values{1, 2, 3};
cout << "The addr of values[0]: " << values.data() << endl;
auto first = values.begin();
auto end = values.end();
values.reserve(20);// 增加values的容量为20
cout << "The addr of values[0]: " << values.data() << endl;
//first = values.begin();
//end = values.end();
while(first != end){
cout << *first;
first ++;
}
cout << endl;
return 0;
}
编译、运行(运行结果可能出错):
PS E:\MyStudy\cplusplus\day02> make
g++ -o stl-vector stl-vector.cpp -g -Wall -std=c++11
PS E:\MyStudy\cplusplus\day02> .\stl-vector.exe
The addr of values[0]: 0xfb0590
The addr of values[0]: 0xfb1c70
16455520164497283
实例7(迭代器重新初始化)
values
容器在增加容量之后,首个元素的存储地址发生了改变,此时再使用先前创建的迭代器,显然是错误的。因此,为了保险起见,每当 vector
容器的容量发生变化时,我们都要对之前创建的迭代器重新初始化一遍:
/*******************************************************************
* > File Name: stl-vector.cpp
* > Create Time: 2021年10月12日 0:43:34
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> values{1, 2, 3};
cout << "The addr of values[0]: " << values.data() << endl;
auto first = values.begin();
auto end = values.end();
values.reserve(20);// 增加values的容量为20
cout << "The addr of values[0]: " << values.data() << endl;
/*容量发生变化,重新申请了内存,需要重新初始化迭代器*/
first = values.begin();
end = values.end();
while(first != end){
cout << *first;//输出元素
first ++;
}
cout << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day16> make stl-vector
g++ -o stl-vector stl-vector.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day16> ./stl-vector.exe
The addr of values[0]: 0x800062170
The addr of values[0]: 0x800084640
123
C++ STL vector容器访问元素的几种方式
访问vector
容器中单个元素
像普通数组那样访问存储的元素,对指定下标处的元素进行修改:
实例8(使用下标[]
访问)
/*******************************************************************
* > File Name: stl-vector1.cpp
* > Create Time: 2021年10月12日 1:06:05
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> values{1, 2, 3, 4, 5};
cout << values[0] << endl;
values[0] = values[1] + values[2] + values[3] + values[4];
cout << values[0] << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day16> make stl-vector1
g++ -o stl-vector1 stl-vector1.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day16> ./stl-vector1.exe
1
14
注意:
容器名[n]
这种获取元素的方式,需要确保下标n
的值不会超过容器的容量(可以通过capacity()
成员函数获取),否则会发生越界访问的错误。vector
容器提供了at()
成员函数,当传给at()
的索引会造成越界时,会抛出std::out_of_range
异常。
实例9(使用at()
函数访问)
/*******************************************************************
* > File Name: stl-vector-at.cpp
* > Create Time: 2021年10月14日 23:14:53
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> values{1,2,3,4,5};
cout << values.at(0) << endl;
values.at(0) = values.at(1) + values.at(2) + values.at(3) + values.at(4);
cout << values.at(0) << endl;
cout << values.at(6) << endl; /*抛出异常*/
cout << "END.\n";
return 0;
}
编译、运行:
PS D:\study\cplusplus\day16> make stl-vector-at
g++ -o stl-vector-at stl-vector-at.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day16> .\stl-vector-at.exe
1
14
terminate called after throwing an instance of 'std::out_of_range'
what(): vector::_M_range_check: __n (which is 6) >= this->size() (which is 5)
1 [main] stl-vector-at 164 cygwin_exception::open_stackdumpfile: Dumping stack trace to stl-vector-at.exe.stackdump
front()
和 back()
函数,分别返回 vector
容器中第一个和最后一个元素的引用,通过引用可以访问(甚至修改)容器中的首尾元素。
实例10(使用front()
和 back()
函数)
/*******************************************************************
* > File Name: stl-vector-front.cpp
* > Create Time: 2021年10月14日 23:26:14
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> values{1,2,3,4,5};
cout << "values首元素:" << values.front() << endl;
cout << "values尾元素:" << values.back() << endl;
values.front() = 10;
values.back() = 100;
cout << "values新首元素:" << values.front() << endl;
cout << "values新尾元素:" << values.back() << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day16> make stl-vector-front
g++ -o stl-vector-front stl-vector-front.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day16> .\stl-vector-front.exe
values首元素:1
values尾元素:5
values新首元素:10
values新尾元素:100
访问vector容器中多个元素
访问 vector
容器中多个元素,可以借助 size()
成员函数,该函数可以返回 vector
容器中实际存储的元素个数。
实例11(使用size()函数)
/*******************************************************************
* > File Name: stl-vector-size.cpp
* > Create Time: 2021年10月16日 11:41:07
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[]){
vector<int> values{1,2,3,4,5};
for(long unsigned int i=0; i < values.size(); i++){
cout << values[i] << " ";
}
cout << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day16> make stl-vector-size
g++ -o stl-vector-size stl-vector-size.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day16> ./stl-vector-size.exe
1 2 3 4 5
注意:这里不要使用
capacity()
成员函数,因为它返回的是vector
容器的容量,而不是实际存储元素的个数,这两者是有差别的
实例12(基于范围的循环)
/*******************************************************************
* > File Name: stl-vector-auto.cpp
* > Create Time: 2021年10月16日 12:18:52
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> values{1,2,3,4,5};
/*基于范围的循环*/
for(auto&& value: values){
cout << value << ' ';
}
cout << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day16> make stl-vector-auto
g++ -o stl-vector-auto stl-vector-auto.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day16> ./stl-vector-auto.exe
1 2 3 4 5
实例13(使用迭代器)
使用 vector
迭代器遍历 vector
容器。
/*******************************************************************
* > File Name: stl-vector-iterator.cpp
* > Create Time: 2021年10月16日 12:27:16
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int> values{1,2,3,4,5};
for(auto first = values.begin(); first < values.end(); ++first){
cout << *first << " ";
}
cout << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day16> make stl-vector-iterator
g++ -o stl-vector-iterator stl-vector-iterator.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day16> ./stl-vector-iterator.exe
1 2 3 4 5
C++ vector
容量(capacity
)和大小(size
)的区别
vector
容器的容量(用 capacity
表示),指的是在不分配更多内存的情况下,容器可以保存的最多元素个数;而 vector
容器的大小(用 size
表示),指的是它实际所包含的元素个数。
实例13(capacity()和size()函数)
/*******************************************************************
* > File Name: stl-vector-reserve.cpp
* > Create Time: 2021年10月16日 17:48:17
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
std::vector<int>values{2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
values.reserve(20);
cout << "values容量:" << values.capacity() << endl;
cout << "values大小:" << values.size() << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day16> make stl-vector-reserve
g++ -o stl-vector-reserve stl-vector-reserve.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day16> ./stl-vector-reserve.exe
values容量:20
values大小:15
显然,vector
容器的大小不能超出它的容量,在大小等于容量的基础上,只要增加一个元素,就必须分配更多的内存。注意:这里的“更多”并不是 1 个。换句话说,当 vector
容器的大小和容量相等时,如果再向其添加(或者插入)一个元素,vector
往往会申请多个存储空间,而不仅仅只申请 1 个。
一旦
vector
容器的内存被重新分配,则和vector
容器中元素相关的所有引用、指针以及迭代器,都可能会失效,最稳妥的方法就是重新生成。
实例14
/*******************************************************************
* > File Name: stl-vector-capacity.cpp
* > Create Time: 2021年10月16日 21:59:15
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>values{2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
cout << "values容量:" << values.capacity() << endl;
cout << "values大小:" << values.size() << endl;
printf("values地址:0X%lX\n", values.data());
values.push_back(53);
cout << "values容量1:" << values.capacity() << endl;
cout << "values大小1:" << values.size() << endl;
printf("values地址1:0X%lX\n", values.data());
return 0;
}
编译、运行:
PS D:\study\cplusplus\day16> ./stl-vector-capacity.exe
values容量:15
values大小:15
values地址:0X800062170
values容量1:30
values大小1:16
values地址1:0X8000846A0
可以看到,向“已满”的 vector
容器再添加一个元素,整个 value
容器的存储位置发生了改变,同时 vector
会一次性申请多个存储空间(具体多少,取决于底层算法的实现)。这样做的好处是,可以很大程度上减少 vector
申请空间的次数,当后续再添加元素时,就可以节省申请空间耗费的时间。
因此,对于
vector
容器而言,当增加新的元素时,有可能很快完成(即直接存在预留空间中);也有可能会慢一些(扩容之后再放新元素)
修改vector
容器的容量和大小
实例15(resize()
函数)
/*******************************************************************
* > File Name: stl-vector-resize.cpp
* > Create Time: 2021年10月16日 22:19:19
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>values{ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47 };
cout << "values容量:" << values.capacity() << endl;
cout << "values大小:" << values.size() << endl;
for(auto&& value: values){
cout << value << " " ;
}
cout << endl;
values.reserve(20);
cout << "values容量1:" << values.capacity() << endl;
cout << "values大小1:" << values.size() << endl;
for(auto&& value: values){
cout << value << " " ;
}
cout << endl;
/*将元素个数改变为 21 个,所以会增加 6 个默认初始化的元素*/
values.resize(21);
cout << "values容量2:" << values.capacity() << endl;
cout << "values大小2:" << values.size() << endl;
for(auto&& value: values){
cout << value << " " ;
}
cout << endl;
/*将元素个数改变为 25 个,所以会增加 4 个默认初始化的元素*/
values.resize(25,99);
cout << "values容量3:" << values.capacity() << endl;
cout << "values大小3:" << values.size() << endl;
for(auto&& value: values){
cout << value << " " ;
}
cout << endl;
/*减少容器的大小*/
values.resize(10);
cout << "values容量4:" << values.capacity() << endl;
cout << "values大小4:" << values.size() << endl;
for(auto&& value: values){
cout << value << " " ;
}
cout << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day16> make stl-vector-resize
g++ -o stl-vector-resize stl-vector-resize.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day16> .\stl-vector-resize.exe
values容量:15
values大小:15
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
values容量1:20
values大小1:15
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47
values容量2:30
values大小2:21
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 0 0 0 0 0 0
values容量3:30
values大小3:25
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 0 0 0 0 0 0 99 99 99 99
values容量4:30
values大小4:10
2 3 5 7 11 13 17 19 23 29
可以看到,仅通过 reserve()
成员函数增加 value
容器的容量,其大小并没有改变;但通过 resize()
成员函数改变 value
容器的大小,它的容量可能会发生改变。另外需要注意的是,通过 resize()
成员函数减少容器的大小(多余的元素会直接被删除),不会影响容器的容量。
vector
容器容量和大小的数据类型
在实际场景中,我们可能需要将容器的容量
和大小
保存在变量中,要知道 vector<T>
对象的容量和大小类型都是 vector<T>::size_type
类型。因此,当定义一个变量去保存这些值时,可以如下所示:
vector<int>::size_type cap = value.capacity();
vector<int>::size_type size = value.size();
size_type
类型是定义在由vector
类模板生成的vecotr
类中的,它表示的真实类型和操作系统有关,在 32 位架构下普遍表示的是unsigned int
类型,而在 64 位架构下普通表示unsigned long
类型。
可以使用 auto
关键字代替 vector<int>::size_type
。
auto cap = value.capacity();
auto size = value.size();
深度剖析C++ vector容器的底层实现机制
STL
众多容器中,vector
是最常用的容器之一,其底层所采用的数据结构非常简单,就只是一段连续的线性内存空间。
分析 vector
容器的源代码可以发现,它就是使用 3 个迭代器(可以理解成指针)来表示的:
//_Alloc 表示内存分配器,此参数几乎不需要我们关心
template <class _Ty, class _Alloc = allocator<_Ty>>
class vector{
...protected:
pointer _Myfirst;
pointer _Mylast;
pointer _Myend;
};
其中,_Myfirst
指向的是 vector
容器对象的起始字节位置;_Mylast
指向当前最后一个元素的末尾字节;_Myend
指向整个 vector
容器所占用内存空间的末尾字节。
在此基础上,将 3 个迭代器两两结合,还可以表达不同的含义,例如:
-
_Myfirst
和_Mylast
可以用来表示vector
容器中目前已被使用的内存空间; -
_Mylast
和_Myend
可以用来表示vector
容器目前空闲的内存空间; -
_Myfirst
和_Myend
可以用表示vector
容器的容量。
对于空的
vector
容器,由于没有任何元素的空间分配,因此_Myfirst
、_Mylast
和_Myend
均为null
。
通过灵活运用这 3 个迭代器,vector
容器可以轻松的实现诸如首尾标识、大小、容器、空容器判断等几乎所有的功能,比如:
template <class _Ty, class _Alloc = allocator<_Ty>>
class vector{
public:
iterator begin() {return _Myfirst;}
iterator end() {return _Mylast;}
size_type size() const {return size_type(end() - begin());}
size_type capacity() const {return size_type(_Myend - begin());}
bool empty() const {return begin() == end();}
reference operator[] (size_type n) {return *(begin() + n);}
reference front() { return *begin();}
reference back() {return *(end()-1);}
...
};
vector
扩大容量的本质
另外需要指明的是,当 vector
的大小和容量相等(size==capacity
)也就是满载时,如果再向其添加元素,那么 vector
就需要扩容。vector
容器扩容的过程需要经历以下 3 步:
- 完全弃用现有的内存空间,重新申请更大的内存空间;
- 将旧内存空间中的数据,按原有顺序移动到新的内存空间中;
- 最后将旧的内存空间释放。
这也就解释了,为什么
vector
容器在进行扩容后,与其相关的指针、引用以及迭代器可能会失效的原因。
由此可见,vector
扩容是非常耗时的。为了降低再次分配内存空间时的成本,每次扩容时 vector
都会申请比用户需求量更多的内存空间(这也就是 vector
容量的由来,即 capacity>=size
),以便后期使用。
vector
容器扩容时,不同的编译器申请更多内存空间的量是不同的。以 VS 为例,它会扩容现有容器容量的50%
。
C++ STL vector添加元素(push_back()和emplace_back())详解
实例16(push_back()
函数):
/*******************************************************************
* > File Name: stl-vector-push_back.cpp
* > Create Time: 2021年10月16日 23:49:05
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>values{};
values.push_back(10);//在尾部添加元素
values.push_back(100);//在尾部添加元素
for(int i = 0; i< values.size(); i++){
cout << values[i] << " ";
}
cout << endl;
return 0;
}
运行:
PS D:\study\cplusplus\day16> .\stl-vector-push_back.exe
10 100
实例17(emplace_back()
函数)
#include <iostream>
#include <vector>
using namespace std;
int main(){
vector<int> values{};
values.emplace_back(1);//在尾部添加元素
values.emplace_back(2);//在尾部添加元素
for (int i = 0; i < values.size(); i++) {
cout << values[i] << " ";
}
return 0;
}
运行:
1 2
emplace_back()
和push_back()
的区别
emplace_back()
和 push_back()
的区别,就在于底层实现的机制不同。push_back()
向容器尾部添加元素时,首先会创建这个元素,然后再将这个元素拷贝或者移动到容器中(如果是拷贝的话,事后会自行销毁先前创建的这个元素);而 emplace_back()
在实现时,则是直接在容器尾部创建这个元素,省去了拷贝或移动元素的过程。
实例18
/*******************************************************************
* > File Name: emplace_back.cpp
* > Create Time: 2021年10月19日 23:41:15
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
class testDemo{
public:
testDemo(int num):num(num){
std::cout << "构造函数" << endl;
}
testDemo(const testDemo& other):num(other.num){
std::cout << "调用拷贝构造函数" << endl;
}
testDemo(testDemo&& other):num(other.num){
std::cout << "调用移动构造函数" << endl;
}
~testDemo(){
std::cout << "析构函数" << endl;
}
private:
int num;
};
int main(int argc, char* argv[])
{
cout << "emplace_back:" << endl;
std::vector<testDemo>demo1;
demo1.emplace_back(2);
cout << "push_back:" << endl;
std::vector<testDemo>demo2;
demo2.push_back(2);
return 0;
}
编译、运行:
PS D:\study\cplusplus\day17> make
g++ -o emplace_back emplace_back.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day17> .\emplace_back.exe
emplace_back:
构造函数
push_back:
构造函数
调用移动构造函数
析构函数
析构函数
析构函数
实例19
/*******************************************************************
* > File Name: emplace_back.cpp
* > Create Time: 2021年10月19日 23:41:15
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
class testDemo{
public:
testDemo(int num):num(num){
std::cout << "构造函数" << endl;
}
testDemo(const testDemo& other):num(other.num){
std::cout << "调用拷贝构造函数" << endl;
}
// testDemo(testDemo&& other):num(other.num){
// std::cout << "调用移动构造函数" << endl;
// }
~testDemo(){
std::cout << "析构函数" << endl;
}
private:
int num;
};
int main(int argc, char* argv[])
{
cout << "emplace_back:" << endl;
std::vector<testDemo>demo1;
demo1.emplace_back(2);
cout << "push_back:" << endl;
std::vector<testDemo>demo2;
demo2.push_back(2);
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day33> make
g++ -o emplace_back emplace_back.cpp -g -Wall -std=c++11
PS E:\fly-prj\cplusplus\day33> .\emplace_back.exe
emplace_back:
构造函数
push_back:
构造函数
调用拷贝构造函数
析构函数
析构函数
析构函数
从实例18和19中看看出,push_back()
在底层实现时,会优先调用移动构造函数,如果没有才会调用拷贝构造函数。
显然完成同样的操作,push_back()
的底层实现过程比 emplace_back()
更繁琐,换句话说,emplace_back()
的执行效率比 push_back()
高。因此,在实际使用时,建议大家优先选用 emplace_back()
。
由于
emplace_back()
是C++ 11
标准新增加的,如果程序要兼顾之前的版本,还是应该使用push_back()
。
C++ STL vector
插入元素(insert()
和emplace()
)详解
vector
容器提供了 insert()
和 emplace()
这 2 个成员函数,用来实现在容器指定位置处插入元素。
insert()
insert()
函数的功能是在 vector
容器的指定位置插入一个或多个元素。
语法格式 | 用法说明 |
| 在迭代器 |
| 在迭代器 |
| 在迭代器 |
| 在迭代器 |
实例20(insert()
)
/*******************************************************************
* > File Name: stl-vector-insert.cpp
* > Create Time: 2021年10月22日 22:32:33
******************************************************************/
#include <iostream>
#include <vector>
#include <array>
using namespace std;
template <typename T>
void printVector(vector<T> vec){
for(auto&& value:vec){
cout << value << " ";
}
cout << endl;
}
int main(int argc, char* argv[])
{
vector<int>values {1,2};
printVector(values);
values.insert(values.begin() + 1, 3);
printVector(values);
values.insert(values.end(), 2, 5);
printVector(values);
std::array<int, 3>test{ 7, 8, 9};
values.insert(values.end(), test.begin(), test.end());
printVector(values);
values.insert(values.end(), {10, 11});
printVector(values);
return 0;
}
编译、运行:
PS D:\study\cplusplus\day17> make stl-vector-insert
g++ -o stl-vector-insert stl-vector-insert.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day17> .\stl-vector-insert.exe
1 2
1 3 2
1 3 2 5 5
1 3 2 5 5 7 8 9
1 3 2 5 5 7 8 9 10 11
emplace()
emplace()
是 C++ 11 标准新增加的成员函数,用于在 vector
容器指定位置之前插入一个新的元素(只能插入一个元素
)。
iterator emplace (const_iterator pos, args...);
其中,pos
为指定插入位置的迭代器;args...
表示与新插入元素的构造函数相对应的多个参数;该函数会返回表示新插入元素位置的迭代器。
实例21(emplace()成员函数
)
/*******************************************************************
* > File Name: stl-vector-emplace.cpp
* > Create Time: 2021年10月24日 21:50:42
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
std::vector<int> demo1{1,2};
demo1.emplace(demo1.begin(), 3);
for(int i = 0; i< demo1.size() ; i++){
cout << demo1[i] << " ";
}
cout << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day17> make stl-vector-emplace
g++ -o stl-vector-emplace stl-vector-emplace.cpp -g -Wall -std=c++11
stl-vector-emplace.cpp: 在函数‘int main(int, char**)’中:
stl-vector-emplace.cpp:16:21: 警告:comparison of integer expressions of different signedness: ‘int’ and ‘std::vector<int>:
:size_type’ {aka ‘long unsigned int’} [-Wsign-compare]
16 | for(int i = 0; i< demo1.size() ; i++){
| ~^~~~~~~~~~~~~~
PS D:\study\cplusplus\day17> ./stl-vector-emplace.exe
3 1 2
实例22(insert()和emplace()函数)
/*******************************************************************
* > File Name: stl-vector-emplace1.cpp
* > Create Time: 2021年10月24日 21:58:16
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
class testDemo{
public:
testDemo(int num):num(num){
std::cout << "调用构造函数" << endl;
}
testDemo(const testDemo& other):num(other.num){
std::cout << "调用拷贝构造函数" << endl;
}
testDemo(testDemo&& other):num(other.num){
std::cout << "调用移动构造函数" << endl;
}
testDemo& operator=(const testDemo& other);
private:
int num;
};
testDemo& testDemo::operator=(const testDemo& other){
this->num = other.num;
return *this;
}
int main(int argc, char* argv[])
{
cout << "Insert:" << endl;
std::vector<testDemo> demo2{};
demo2.insert(demo2.begin(), testDemo(1));
cout << "emplace: " << endl;
std::vector<testDemo> demo1{};
demo1.emplace(demo1.begin(), 1);
return 0;
}
编译、运行:
PS D:\study\cplusplus\day17> make stl-vector-emplace1
g++ -o stl-vector-emplace1 stl-vector-emplace1.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day17> .\stl-vector-emplace1.exe
Insert:
调用构造函数
调用移动构造函数
emplace:
调用构造函数
注意,当拷贝构造函数和移动构造函数同时存在时,
insert()
会优先调用移动构造函数。
emplace()
和 insert()
都能完成向 vector
容器中插入新元素,通过上面程序运行可知,emplace()
比insert()
效率更高。emplace()
在插入元素时,是在容器的指定位置直接构造元素,而不是先单独生成,再将其复制(或移动)到容器中。
C++ STL vector
删除元素的几种方式(超级详细)
删除 vector
容器元素的几种方式:
函数 | 功能 |
| 删除 |
| 删除 |
| 先调用 |
| 删除 |
| 删除容器中所有和指定元素值相等的元素,并返回指向最后一个元素下一个位置的迭代器。值得一提的是,调用该函数不会改变容器的大小和容量。 |
| 删除 |
实例23(pop_back()
函数)
/*******************************************************************
* > File Name: vector-pop_back.cpp
* > Create Time: 2021年11月 1日 23:51:03
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>demo{1, 2, 3, 4, 5};
demo.pop_back(); /*删除最后一个元素*/
cout << "size is :" << demo.size() << endl; /*输出容器的大小*/
cout << "capacity is :" << demo.capacity() << endl; /*输出容器的容量*/
for(int i=0; i< demo.size(); i++){
cout << demo[i] << " "; /*遍历输出容器中的元素*/
}
cout << endl;
return 0;
}
编译、运行:
PS D:\study\cplusplus\day18> make
g++ -o vector-pop_back vector-pop_back.cpp -g -Wall -std=c++11
PS D:\study\cplusplus\day18> .\vector-pop_back.exe
size is :4
capacity is :5
1 2 3 4
实例24(erase()
函数)
/*******************************************************************
* > File Name: vector-erase.cpp
* > Create Time: 2021年11月 1日 23:56:50
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>demo {1, 2, 3, 4, 5};
auto iter = demo.erase(demo.begin() + 1);
cout << "size is :" << demo.size() << endl;
cout << "capacity is :" << demo.capacity() << endl;
for(int i=0; i< demo.size(); i++){
cout << demo[i] << " ";
}
cout << endl << *iter << endl;
return 0;
}
运行结果:
PS D:\study\cplusplus\day18> .\vector-erase.exe
size is :4
capacity is :5
1 3 4 5
3
实例25(swap()
和pop_back()
函数)
/*******************************************************************
* > File Name: vector-swap.cpp
* > Create Time: 2021年11月 2日 22:08:06
******************************************************************/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>demo{1,2,3,4,5};
swap(*(std::begin(demo)+1), *(std::end(demo)-1));/*交换元素*/
for(int i = 0; i< demo.size(); i++){
cout << demo[i] << " ";
}
cout << endl;
demo.pop_back();/*移除容器最后一个元素*/
cout << "size is : " << demo.size() << endl;
cout << "capacity is : " << demo.capacity() << endl;
for(int i = 0; i< demo.size(); i++){
cout << demo[i] << " ";
}
cout << endl;
return 0;
}
运行:
PS D:\study\cplusplus\day18> .\vector-swap.exe
1 5 3 4 2
size is : 4
capacity is : 5
1 5 3 4
实例26(erase(begin, end)
函数)
/*******************************************************************
* > File Name: vector-erase1.cpp
* > Create Time: 2021年11月 2日 22:19:16
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
std::vector<int>demo{1, 2, 3, 4, 5, 6};
//删除2,3,4
auto iter = demo.erase(demo.begin()+1, demo.end()-3);
cout << "*iter is : " << *iter << endl;
cout << "size is :" << demo.size() << endl;
cout << "capacity is : " << demo.capacity() << endl;
for(int i = 0; i< demo.size(); i++){
cout << demo[i] << " ";
}
cout << endl;
return 0;
}
运行:
PS D:\study\cplusplus\day18> .\vector-erase1.exe
*iter is : 4
size is :4
capacity is : 6
1 4 5 6
实例27(remove()
函数)
/*******************************************************************
* > File Name: stl-vector-remove.cpp
* > Create Time: 2021年11月 7日 9:21:01
******************************************************************/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
std::vector<int>demo{1, 3, 3, 4, 3, 5};
auto iter = std::remove(demo.begin(), demo.end() , 3);
cout << "iter is : " << *iter << endl;
cout << "size is : " << demo.size() << endl;
cout << "capacity is : " << demo.capacity() << endl;
for(auto first = demo.begin(); first < iter ; ++ first){
cout << *first << " ";
}
cout << endl;
for(int i = 0; i < demo.capacity(); i++){
cout << demo[i] << " ";
}
cout << endl;
return 0;
}
运行:
PS E:\MyStudy\cplusplus\day1> .\stl-vector-remove.exe
iter is : 4
size is : 6
capacity is : 6
1 4 5
1 4 5 4 3 5
remove()
的实现原理是,在遍历容器中的元素时,一旦遇到目标元素,就做上标记,然后继续遍历,直到找到一个非目标元素,即用此元素将最先做标记的位置覆盖掉,同时将此非目标元素所在的位置也做上标记,等待找到新的非目标元素将其覆盖。因此,如果将上面程序中demo
容器的元素全部输出,得到的结果为1 4 5 4 3 5
。
实例28(remove()函数)
通过实例27运行可知,remove
函数删除demo
中的多个指定元素,容器的大小和容量都没有变化,其剩余位置还保留了之前存储的元素,使用erase
函数可以删除这些元素。
/*******************************************************************
* > File Name: stl-vector-remove1.cpp
* > Create Time: 2021年11月 7日 9:49:43
******************************************************************/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
vector<int>demo{1, 3, 3, 4, 3, 5};
auto iter = std::remove(demo.begin(), demo.end(), 3);
demo.erase(iter, demo.end());
cout << "size is : " << demo.size() << endl;
cout << "capacity is : " << demo.capacity() << endl;
for(int i = 0; i < demo.size() ; i++){
cout << demo[i] << " " ;
}
cout << endl;
return 0;
}
编译、运行:
PS E:\MyStudy\cplusplus\day1> .\stl-vector-remove1.exe
size is : 3
capacity is : 6
1 4 5
实例29(clear()
函数)
/*******************************************************************
* > File Name: stl-vector.clear.cpp
* > Create Time: 2021年11月 7日 10:01:06
******************************************************************/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(void)
{
vector<int>demo{1, 3, 3, 4, 3, 5};
demo.clear();
cout << "size is : " << demo.size() << endl;
cout << "capacity is : " << demo.capacity() << endl;
return 0;
}
编译、运行:
PS E:\MyStudy\cplusplus\day1> .\stl-vector_clear.exe
size is : 0
capacity is : 6
如何避免vector
容器进行不必要的扩容?
vector
容器扩容的整个过程,和 realloc()
函数的实现方法类似,大致分为以下 4 个步骤:
分配一块大小是当前
vector
容量几倍的新存储空间。注意,多数STL
版本中的vector
容器,其容器都会以 2 的倍数增长,也就是说,每次vector
容器扩容,它们的容量都会提高到之前的 2 倍;将
vector
容器存储的所有元素,依照原有次序从旧的存储空间复制到新的存储空间中;析构掉旧存储空间中存储的所有元素;
释放旧的存储空间。
vector
容器的扩容过程是非常耗时的,并且当容器进行扩容后,之前和该容器相关的所有指针、迭代器以及引用都会失效。因此在使用 vector
容器过程中,我们应尽量避免执行不必要的扩容操作。
vector
模板类中功能类似的成员方法:
成员方法 | 功能 |
| 告诉我们当前 |
| 告诉我们当前 |
| 强制 |
| 强制 |
**总结:**只要有新元素要添加到 vector
容器中而恰好此时 vector
容器的容量不足时,该容器就会自动扩容。
因此,避免 vector
容器执行不必要的扩容操作的关键在于,在使用 vector
容器初期,就要将其容量设为足够大的值。换句话说,在 vector
容器刚刚构造出来的那一刻,就应该借助 reserve()
成员方法为其扩充足够大的容量。
实例30
假设我们想创建一个包含 1~1000 的 vector<int>
,通常会这样实现:
vector<int>myvector;
for (int i = 1; i <= 1000; i++) {
myvector.push_back(i);
}
上面代码的整个循环过程中,vector
容器会进行 2~10 次自动扩容(多数的 STL
标准库版本中,vector
容器通常会扩容至当前容量的 2 倍,而这里 1000≈2 ^ 10),程序的执行效率可想而知。
实例31
使用reserve()方法尽量避免vector容器的不必要的扩容操作。
vector<int>myvector;
myvector.reserve(1000);
cout << myvector.capacity();
for (int i = 1; i <= 1000; i++) {
myvector.push_back(i);
}
相比前面的代码实现,整段程序在运行过程中,vector
容器的容量仅扩充了 1 次,执行效率大大提高。
当然在实际场景中,我们可能并不知道 vector
容器到底要存储多少个元素。这种情况下,可以先预留出足够大的空间,当所有元素都存储到 vector
容器中之后,再去除多余的容量。
关于怎样去除
vector
容器多余的容量,可以借助该容器模板类提供的shrink_to_fit()
成员方法。
vector swap()
成员方法还可以这样用!
实例32
在使用 vector
容器的过程中,其容器会根据需要自行扩增。比如,使用 push_back()
、insert()
、emplace()
等成员方法向 vector
容器中添加新元素时,如果当前容器已满(即 size() == capacity()
),则它会自行扩容以满足添加新元素的需求。当然,还可以调用 reserve()
成员方法来手动提升当前 vector
容器的容量。
/*******************************************************************
* > File Name: stl-vector1.cpp
* > Create Time: 2021年11月18日 11:08:53
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>myvector;//定义一个向量容器myvector
cout << "1.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
for(int i = 1; i <= 10; i++){
myvector.push_back(i); /* 存储10个元素 */
}
cout << "2.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
myvector.reserve(1000); /* 手动扩容 */
cout << "3.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
return 0;
}
运行:
PS E:\fly-prj\cplusplus\day34> make
g++ -o stl-vector1 stl-vector1.cpp -g -Wall
PS E:\fly-prj\cplusplus\day34> .\stl-vector1.exe
1.myvector size :0 , capacity : 0
2.myvector size :10 , capacity : 16
3.myvector size :10 , capacity : 1000
实例33
/*******************************************************************
* > File Name: stl-vector2.cpp
* > Create Time: 2021年11月18日 11:22:08
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>myvector;//定义一个向量容器myvector
cout << "1.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
for(int i = 1; i <= 10; i++){
myvector.push_back(i); /* 存储10个元素 */
}
cout << "2.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
myvector.reserve(1000); /* 手动扩容 */
cout << "3.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
myvector.erase(myvector.begin()); /* 删除容器myvector起始位置的元素 */
cout << "4.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
myvector.pop_back(); /* 删除容器中最后一个元素 */
cout << "5.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
myvector.clear(); /* 清除所有元素 */
cout << "6.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day34> make
g++ -o stl-vector2 stl-vector2.cpp -g -Wall
PS E:\fly-prj\cplusplus\day34> .\stl-vector2.exe
1.myvector size :0 , capacity : 0
2.myvector size :10 , capacity : 16
3.myvector size :10 , capacity : 1000
4.myvector size :9 , capacity : 1000
5.myvector size :8 , capacity : 1000
6.myvector size :0 , capacity : 1000
实例34(shrink_to_fit()函数
)
/*******************************************************************
* > File Name: stl-vector3.cpp
* > Create Time: 2021年11月18日 12:54:10
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>myvector;//定义一个向量容器myvector
cout << "1.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
for(int i = 1; i <= 10; i++){
myvector.push_back(i); /* 存储10个元素 */
}
cout << "2.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
myvector.reserve(1000); /* 手动扩容 */
cout << "3.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
myvector.erase(myvector.begin()); /* 删除容器myvector起始位置的元素 */
cout << "4.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
myvector.pop_back(); /* 删除容器中最后一个元素 */
cout << "5.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
myvector.clear(); /* 清除所有元素 */
cout << "6.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
myvector.shrink_to_fit();/* 将容器的容量缩减至和实际元素个数相等 */
cout << "7.myvector size :" << myvector.size() << " , capacity : " << myvector.capacity() << endl;
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day34> make
g++ -o stl-vector3 stl-vector3.cpp -g -Wall
PS E:\fly-prj\cplusplus\day34> .\stl-vector3.exe
1.myvector size :0 , capacity : 0
2.myvector size :10 , capacity : 16
3.myvector size :10 , capacity : 1000
4.myvector size :9 , capacity : 1000
5.myvector size :8 , capacity : 1000
6.myvector size :0 , capacity : 1000
7.myvector size :0 , capacity : 0
利用swap()方法去除vector多余容量
实例35
/*******************************************************************
* > File Name: stl-vector-swap.cpp
* > Create Time: 2021年11月18日 13:05:42
******************************************************************/
#include <iostream>
#include <vector>
using namespace std;
int main(int argc, char* argv[])
{
vector<int>myvector;
myvector.reserve(1000);
cout << "1.myvector size : " << myvector.size() << " , capacity : " << myvector.capacity() << endl;
for(int i = 1; i<= 10; i++){
myvector.push_back(i);
}
vector<int>(myvector).swap(myvector);
cout << "2.myvector size : " << myvector.size() << " , capacity : " << myvector.capacity() << endl;
return 0;
}
编译、运行:
PS E:\fly-prj\cplusplus\day34> make
g++ -o stl-vector-swap stl-vector-swap.cpp -g -Wall
PS E:\fly-prj\cplusplus\day34> .\stl-vector-swap.exe
1.myvector size : 0 , capacity : 1000
2.myvector size : 10 , capacity : 10