浅谈C++|STL之vector篇

本文详细介绍了C++标准库中的vector容器,包括其动态大小、连续存储特性、自动扩展、插入和删除操作,以及各种赋值、大小、容量和内存管理函数。还展示了vector与其他数组的差异以及如何利用swap进行内存优化。
摘要由CSDN通过智能技术生成

在这里插入图片描述

一.vector的基本概念

vector是C++标准库中的一种动态数组容器,提供了动态大小的数组功能,能够在运行时根据需要自动扩展和收缩。vector以连续的内存块存储元素,可以快速访问和修改任意位置的元素。

以下是vector的基本概念和特点:

  1. 动态大小:vector可以动态地调整其大小,可以在运行时根据需要添加或删除元素。与静态数组不同,vector不需要在定义时指定固定的元素个数。

  2. 连续存储:vector以连续的内存块存储元素。这样的存储方式使得访问元素变得高效,可以通过索引快速访问和修改任意位置的元素。

  3. 自动扩展和收缩:vector可以根据需要自动扩展以容纳更多的元素,并在需要时自动收缩以节省内存。这样,您无需手动管理内存,vector会自动处理。

  4. 插入和删除:vector提供了多种方法来插入和删除元素。可以在任意位置插入元素,也可以从任意位置删除元素,包括头部和尾部。

  5. 随机访问:vector支持快速的随机访问。可以使用索引来直接访问任意位置的元素,时间复杂度为O(1)。

  6. 迭代器支持:vector提供迭代器来遍历容器中的元素。迭代器可以用于读取和修改容器中的元素,支持正向和反向迭代。

vector是一个非常常用和灵活的容器,适用于需要动态调整大小的数组存储需求。它在许多应用中都很有用,例如数据的动态收集、动态分配的数组、实现栈和队列等。

功能:

vector教据结构和数组非常相似,也称为单端数组

vector与普通数组的区别

不同之处在于数组是静态空间,而vector可以动态扩展

动态扩展

并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间

二.vector赋值操作

vector提供了几种不同的函数和操作符用于赋值操作。以下是常用的vector赋值操作的函数原型:

  1. operator= 操作符:
vector& operator=(const vector& other);

该操作符用于将一个vector赋值给另一个vector,使它们包含相同的元素。该操作符返回一个引用,允许连续赋值。

  1. assign() 函数:
void assign(size_type count, const T& value);
template<typename InputIt>
void assign(InputIt first, InputIt last);
void assign(std::initializer_list<T> ilist);

assign() 函数用于将指定的值、范围或初始化列表中的元素赋值给vector。第一个版本接受指定数量的元素值;第二个版本接受范围指针,可以使用迭代器指定范围;第三个版本接受一个初始化列表。

  1. swap() 函数:
void swap(vector& other);

swap() 函数用于交换两个vector的内容,将当前vector与另一个vector的元素进行交换。

整理成表格,以方便查阅。

函数函数原型描述
operator=vector& operator=(const vector& other);将一个vector赋值给另一个vector,使它们包含相同的元素。
assign()void assign(size_type count, const T& value);将指定数量的元素值赋值给vector
template<typename InputIt> void assign(InputIt first, InputIt last);将范围指针指定的元素赋值给vector
void assign(std::initializer_list<T> ilist);将初始化列表中的元素赋值给vector
swap()void swap(vector& other);交换两个vector的内容。

三.vextor的大小和容量

vector提供了一些函数用于获取容量和大小相关的信息。以下是vector的容量和大小函数的原型:

  1. size() 函数:
size_type size() const;

此函数返回vector当前包含的元素数量,也就是vector的大小。

  1. max_size() 函数:
size_type max_size() const;

该函数返回vector可以容纳的最大元素数量,考虑到系统限制和内存限制。

  1. resize() 函数:
void resize(size_type count);
void resize(size_type count, const T& value);

此函数用于调整vector的大小,可以增加或减少元素的数量。第一个版本将vector的大小调整为指定的 count,第二个版本还可以指定当扩展vector大小时,默认填充的元素值。

  1. capacity() 函数:
size_type capacity() const;

该函数返回当前vector的容量,即能够在重新分配内存之前持有的元素数量,以节省内存重新分配的开销。

  1. reserve() 函数:
void reserve(size_type new_cap);

此函数用于增加vector的容量,使其至少能够容纳指定数量的元素,但不为元素分配实际值。这可以提前分配所需的内存,以减少因调整大小而引起的内存重新分配的次数。

整理成表格:

函数函数原型描述
size()size_type size() const;返回vector当前包含的元素数量,即vector的大小。
max_size()size_type max_size() const;返回vector可以容纳的最大元素数量,受系统限制和内存限制约束。
empty()bool empty() const;判断vector是否为空,若为空则返回true,否则返回false
resize()void resize(size_type count);
void resize(size_type count, const T& value);
调整vector的大小,增加或减少元素数量。
第一个版本将vector的大小调整为指定的count
第二个版本在扩展vector大小时,指定默认的填充元素值。
capacity()size_type capacity() const;返回当前vector的容量,即为元素重新分配内存之前可以容纳的元素数量,以节省内存重新分配的开销。
reserve()void reserve(size_type new_cap);增加vector的容量,使其至少能够容纳指定数量的元素,但不为元素分配实际值。这样可以减少内存重新分配的次数。

四.vector插入和删除

整理成表格:

函数函数原型描述
insert()iterator insert(iterator pos, const T& value);
iterator insert(iterator pos, size_type count, const T& value);
在指定位置插入元素到vector中,并返回插入的位置迭代器。
第一个版本可以插入单个元素。
第二个版本可以插入指定数量的相同元素。
emplace()template <class... Args> iterator emplace(iterator pos, Args&&... args);在指定位置就地构造一个元素,并返回插入的位置迭代器。
erase()iterator erase(iterator pos);
iterator erase(iterator first, iterator last);
vector中删除指定位置或范围的元素,并返回下一个元素的位置迭代器。
clear()void clear();vector中移除所有的元素,使其变为空。
push_back()void push_back(const T& value);将元素添加到vector的末尾。
emplace_back()template <class... Args> reference emplace_back(Args&&... args);vector的末尾就地构造一个元素。
pop_back()void pop_back();移除vector的最后一个元素。

请注意,表中的函数参数使用的是迭代器(iterator),而非常数迭代器(const_iterator)。这是因为插入和删除操作会改变容器的内容,所以需要可变的迭代器来指向和修改元素。

五.vector数据的存取

下面是vector的数据存取操作函数的函数原型整理成表格:

函数函数原型描述
at()reference at(size_type pos);
const_reference at(size_type pos) const;
返回指定位置的元素的引用。
pos超出范围,会抛出out_of_range异常。
operator[]()reference operator[](size_type pos);
const_reference operator[](size_type pos) const;
返回指定位置的元素的引用。
不进行范围检查,使用时需确保索引有效。
front()reference front();
const_reference front() const;
返回vector中第一个元素的引用。
back()reference back();
const_reference back() const;
返回vector中最后一个元素的引用。
data()T* data();
const T* data() const;
返回指向vector中第一个元素的指针。
vector为空,返回空指针。

以上是常用的vector数据存取操作的函数原型。您可以根据需要使用它们来访问和修改vector中的元素。

六.vector的容器交换

vector的容器互换操作可以使用swap()函数来实现。swap()函数可以交换两个容器的内容,具体的函数原型如下:

template <class T, class Alloc>
void swap(vector<T,Alloc>& x, vector<T,Alloc>& y) noexcept;

其中,xy是要互换内容的两个 vector 容器。使用swap()函数可以快速高效地交换两个 vector 的内容,而不需要逐个元素进行复制或移动。

下面是一个简单的示例演示如何使用 swap() 函数交换两个 vector 的内容:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec1 = {1, 2, 3, 4};
    std::vector<int> vec2 = {5, 6, 7, 8};

    // 输出交换前的内容
    std::cout << "vec1: ";
    for (const auto& num : vec1) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    std::cout << "vec2: ";
    for (const auto& num : vec2) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    // 交换容器内容
    std::swap(vec1, vec2);

    // 输出交换后的内容
    std::cout << "vec1: ";
    for (const auto& num : vec1) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    std::cout << "vec2: ";
    for (const auto& num : vec2) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}

运行以上代码,将会输出如下结果:

vec1: 1 2 3 4 
vec2: 5 6 7 8 
vec1: 5 6 7 8 
vec2: 1 2 3 4

通过 swap() 函数,vec1vec2 的内容被互换了。这个操作非常高效,因为只涉及到指针的交换,而不需要逐个元素进行复制或移动。

巧用swap收缩内存空间

swap()函数还可以用于收缩vector内存空间,从而释放不需要的内存。通过将一个空的vector与目标vector进行交换,可以使目标vector的容量缩小到与其当前大小相匹配。

这是因为当swap()函数交换两个vector时,目标vector会获得另一个vector的内存空间,而那个被交换的vector则会获得一个空的内存空间。然后,由于交换后的vector大小与容量相匹配,多余的内存会被释放。

以下是一个示例代码,展示了如何通过swap()函数收缩vector的内存空间:

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec;

    // 向vector中添加大量数据
    for (int i = 0; i < 1000000; ++i) {
        vec.push_back(i);
    }

    std::cout << "Size before shrink: " << vec.size() << std::endl;
    std::cout << "Capacity before shrink: " << vec.capacity() << std::endl;

    // 收缩内存空间
    std::vector<int>(vec).swap(vec);

    std::cout << "Size after shrink: " << vec.size() << std::endl;
    std::cout << "Capacity after shrink: " << vec.capacity() << std::endl;

    return 0;
}

运行以上代码,将会输出如下结果:

Size before shrink: 1000000
Capacity before shrink: 1048576
Size after shrink: 1000000
Capacity after shrink: 1000000

通过使用swap()函数将一个空的vector和目标vector交换,我们成功缩小了vec的内存空间,使其容量与其大小相匹配。注意,swap()函数的参数是通过使用临时vector构造的,以避免影响到原始vec的值。

请注意,这种技巧并不适用于C++11标准之前的版本,因为在C++11之前,vector的移动语义不是必须的,而可能导致复制操作而不是交换操作。因此,在使用旧标准的编译器中,最好使用shrink_to_fit()函数来请求收缩内存,这是C++11引入的函数,并作为标准函数来直接缩小容器的内存空间。
七.函数接口总结

以下是一些对std::vector的扩展函数和成员类型:

函数或成员类型描述
std::vector::emplace_hint在指定位置的提示前插入元素
std::vector::insert_or_assign插入元素或修改现有元素的值
std::vector::erase移除指定位置或指定范围的元素
std::vector::erase_if根据给定的谓词函数删除元素
std::vector::remove移除指定值的所有元素
std::vector::remove_if根据给定的谓词函数删除元素
std::vector::swap交换两个向量的内容
std::vector::merge合并两个已排序的向量,并将结果存储在第一个向量中
std::vector::sort对向量的元素进行排序
std::vector::stable_sort对向量的元素进行稳定排序
std::vector::reverse反转向量中元素的顺序
std::vector::unique移除重复的元素,仅保留相邻的一个
std::vector::unique根据给定的谓词函数移除重复的元素
std::vector::binary_search使用二分查找在排序的向量中查找元素
std::vector::lower_bound返回一个迭代器,指向在已排序向量中首次出现不小于给定值的元素位置
std::vector::upper_bound返回一个迭代器,指向在已排序向量中首次出现大于给定值的元素位置
std::vector::equal_range返回一个pair,其中第一个迭代器是lower_bound返回值,第二个迭代器是upper_bound返回值
std::vector::rbegin返回指向最后一个元素的反向迭代器
std::vector::rend返回指向第一个元素之前位置的反向迭代器
std::vector::cbegin返回指向第一个元素的常量迭代器
std::vector::cend返回指向最后一个元素之后位置的常量迭代器
std::vector::crbegin返回指向最后一个元素的反向常量迭代器
std::vector::crend返回指向第一个元素之前位置的反向常量迭代器
std::vector::max_size返回向量能容纳的最大元素数量
std::vector::reserve提前预留指定的容量,以减少重新分配内存的次数
std::vector::emplace_hint在指定位置的提示前插入元素
std::vector::insert_or_assign插入元素或修改现有元素的值
std::vector::get_allocator返回与向量关联的内存分配器
std::vector::operator==判断两个向量是否相等
std::vector::operator!=判断两个向量是否不相等
std::vector::operator<比较两个向量的字典序
std::vector::operator<=判断一个向量是否小于等于另一个向量
std::vector::operator>判断一个向量是否大于另一个向量
std::vector::operator>=判断一个向量是否大于等于另一个向量
std::vector::emplace_hint在指定位置的提示前插入元素
std::vector::insert_or_assign插入元素或修改现有元素的值
std::vector::erase移除指定位置或指定范围的元素
std::vector::erase_if根据给定的谓词函数删除元素
std::vector::remove移除指定值的所有元素
std::vector::remove_if根据给定的谓词函数删除元素
std::vector::swap交换两个向量的内容
std::vector::merge合并两个已排序的向量,并将结果存储在第一个向量中
std::vector::sort对向量的元素进行排序
std::vector::stable_sort对向量的元素进行稳定排序
std::vector::reverse反转向量中元素的顺序
std::vector::unique移除重复的元素,仅保留相邻的一个
std::vector::unique根据给定的谓词函数移除重复的元素
std::vector::binary_search使用二分查找在排序的向量中查找元素
std::vector::lower_bound返回一个迭代器,指向在已排序向量中首次出现不小于给定值的元素位置
std::vector::upper_bound返回一个迭代器,指向在已排序向量中首次出现大于给定值的元素位置
std::vector::equal_range返回一个pair,其中第一个迭代器是lower_bound返回值,第二个迭代器是upper_bound返回值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

左手的月光

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

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

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

打赏作者

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

抵扣说明:

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

余额充值