STL容器之vector

一. vector的特点

  • 支持元素的随机存取。常数时间
  • 提供的是随机访问迭代器,可适用于stl的所有算法
  • 在尾部插入/删除元素比较快速(均摊)。
  • 在头部、中间插入元素非常缓慢。

vector相关操作

构造函数和析构函数

构造函数描述
vector<ElemType > v默认构造函数,
vector<ElemType> v(v1)Copy构造函数
vector<ElemType> v = v1Copy构造函数
vector<ElemType> v(n)利用ElemType的默认构造函数创建一个大小为n的vector
vector<ElemType> v(n, value)创建一个大小为n的vector,每个元素的值都为value的拷贝。
vector<ElemType> v(begin,end)从区间[begin,end)创建一个vector
vector<ElemType> v(initializer_list)以初始化列表创建一个vector(始自C++11)
vector<ElemType> v = initializer_list以初始化列表创建一个vector(始自C++11)

示例代码:

//默认构造函数.创建一个空的vector,不包含任何元素,v.size()为0,v.capacity()为0.
std::vector<int> v;
vector_size_capacity_printer(v, "v: ");

//std::vector<int> v(initializer_list). 使用初始化列表的方式创建vector.
std::vector<int> v1{0,1,2,3,4,5,6,7,8,9};
vector_size_capacity_printer(v1,"v1: ");
ElementPrinter(v1, "v1: ");

//std::vector<int> v = {initializer_list}.使用初始化列表的方式创建vector.
std::vector<int> v2 = {0,1,2,3,4,5,6,7,8,9};

//std::vector<int> v(begin,end).使用同类型vector的某个区间构造vector
std::vector<int> v3(v2.begin(), v2.end());

//std::vector<ElemType> v(n) 创建按包含n个元素的vector,每个元素都以ElemType的默认构造函数构建。
std::vector<int> v4(10);

//std::vector<ElemType> v(n, elem) 创建按包含n个元素的vector,每个元素都是elem的副本
std::vector<int> v5(10, 2);

//std::vector<int> v1(v). 拷贝构造函数.
std::vector<int> v6(v5);

//std::vector<int> v1 = v.拷贝构造函数.
std::vector<int> v7(v1);

大小(Size)和容量(Capacity)

赋值(assignment)操作

vector赋值相关操作

相关操作描述
v = v1赋值运算符。将v1的全部元素赋值给v
v = rv移动赋值运算符。(始自C++11)
v = initializer_list将初始化列表initializer_list的所有元素赋值给v。(始自C++11)
v.assign(n, elem)将n个elem赋值给v。
v.assign(beign,end)将区间[begin,end)的元素赋值给v。
v.assign(initializer_list)将初始化列表initializer_list的所有元素赋值给v。始自C++11)
v.swap(v1)交换v和v1的元素
swap(v,v1)交换v和v1的元素

元素访问

元素访问相关操作

相关操作描述
v[index]通过下标运算符[]的方式访问元素,不进行越界检查
v.at(index)返回index指向的元素。会进行越界检查。
v.front()返回第一个元素 (不检查第一个元素是否存在)
v.back()返回最后一个元素。 (不检查最后一个元素是否存在)

迭代器

插入(Insert)和移除(Remove)元素

插入操作

插入操作描述
v.push_back(elem)在v的末尾插入一个元素(elem的拷贝)。无返回值。
v.insert(pos, elem)在pos之前插入一个元素(elem的拷贝)。返回指向新元素的迭代器
v.insert(pos,num,elem)在pos之前插入num个元素(每个元素都是elem的拷贝)。返回指向第一个新元素的迭代器(或返回pos–没插入新元素)
v.insert(pos,begin,end)在pos之前插入[beign,end)区间内的所有元素。返回指向第一个新元素的迭代器(或返回pos–没插入新元素)
v.insert(pos,initializer_list)在pos之前插入initializer_list内的所有元素。返回指向第一个新元素的迭代器(或返回pos–没插入新元素)。(始自C++11)
v.emplace(pos,args…)在pos之前插入一个元素(以arg为初始值,arg必须和元素类型的某个构造函数参数匹配)。返回新元素的位置。(始自C++11)
v.emplace(args…)在v的末尾插入一个元素(以arg为初始值,arg必须和元素类型的某个构造函数参数匹配)。无返回值。(始自C++11)

移除操作

移除操作描述
v.pop_back()通过下标运算符[]的方式访问元素,不进行越界检查
v.erase(pos)移除迭代器pos指向的元素。返回下一个元素的位置
v.erase(begin,end)移除区间[begin,end)内的所有元素,返回下一个元素的位置。
v.clear()移除所有元素。此时v.size()=0,v.capacity()不变。

resize()函数

移除操作描述
v.resize(num)该变v的大小.如果num>v.size(),多出来的元素以默认构造函数进行初始化。如果num == v.szie()则不做任何操作;如果num < v.size(),则从vector的末尾移除(num-v.size())个元素。该操作不改变vector的容量。
v.resize(num, elem)该变v的大小.如果num>v.size(),多出来的元素都是elem的副本。如果num == v.szie()则不做任何操作;如果num < v.size(),则从vector的末尾移除(num-v.size())个元素。该操作不改变vector的容量。

之所以将resize单独列出来说明,因为resize既可以当做移除操作,也可以当做插入操作,这取决于num与size()的大小关系。

删除vector中满足条件所有元素

std::vector并没有提供任何成员函数用以直接移除“满足某一条件”的所有元素。
首先想到的应该是使用std::remove算法:

std::vector<int> Nums;
Nums.reserve(10);

for(int i = 1; i <10;++i){
    Nums.push_back(i);
}

Nums[0] = Nums[3] = Nums[5] = Nums[7] = Nums[8] = 88;
ElementPrinter(Nums, "init vector: ");

std::remove(Nums.begin(), Nums.end(), 88);
ElementPrinter(Nums , "after remove vector: ");

上面示例中,我们的目的是删除所有值等于(==)88的元素。我们期望的结果是:

2 3 5 7

运行结果:

init vector: 88 2 3 88 5 88 7 88 88
after remove vector: 2 3 5 7 5 88 7 88 88

显然,运行结果跟我们期望不符,那么是什么原因造成的呢?答案是,std::remove算法的实现造成的:以不会被删除的元素覆盖需要删除的元素,不会真正的删除元素,也不会改变的容器的大小。

请记住:要删除容器元素的唯一方式是调用容器的成员函数。std::remove()算法没有任何一个参数是以容器为参数。这就是std::remove算法无法删除容器元素的根本原因。

下面介绍可以真正删除vector容器中元素的两种方式。

remove-erase方式(推荐)

std::vector<int> Nums;
Nums.reserve(10);

for(int i = 1; i <10;++i){
   Nums.push_back(i);
}

Nums[0] = Nums[3] = Nums[5] = Nums[7] = Nums[8] = 88;
ElementPrinter(Nums, "init vector: ");

//remove-erase方式
Nums.erase(std::remove(Nums.begin(), Nums.end(), 88),Nums.end());
ElementPrinter(Nums , "after remove vector: ");

输出:

init vector: 88 2 3 88 5 88 7 88 88
after remove vector: 2 3 5 7

基于for循环的方式

std::vector<int> Nums;
Nums.reserve(10);

for(int i = 1; i <10;++i){
    Nums.push_back(i);
}

Nums[0] = Nums[3] = Nums[5] = Nums[7] = Nums[8] = 88;
ElementPrinter(Nums, "init vector: ");

//基于for循环的方式:满足条件时迭代器不++,否则++
for(std::vector<int>::iterator it = Nums.begin(); it != Nums.end();){
    if(88 == *it){
        Nums.erase(it);
    }else {
        ++it;
    }
    
}

ElementPrinter(Nums , "after remove vector: ");

输出:

init vector: 88 2 3 88 5 88 7 88 88
after remove vector: 2 3 5 7

辅助函数

//打印元素
template <typename T>
void ElementPrinter(const T &inVec, const string & HintString)
{
    std::cout << HintString ;
    
    std::for_each(inVec.begin(), inVec.end(), 
                  [](const int &Elem){
        std::cout << Elem << " ";
    });
    
	std::cout << std::endl;
}

//打印容量和大小
void VectorSampeleCode::vector_size_capacity_printer(const std::vector<int> &inVector, const std::string &HintString)
{
    std::cout << HintString ;
    
    std::cout << "size = " << inVector.size() << " capacity = " << inVector.capacity() << std::endl;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Oak24

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值