c++ 11标准模板(STL) std::vector (八)

定义于头文件 <vector>
template<

    class T,
    class Allocator = std::allocator<T>

> class vector;
(1)
namespace pmr {

    template <class T>
    using vector = std::vector<T, std::pmr::polymorphic_allocator<T>>;

}
(2) (C++17 起)

 1) std::vector 是封装动态数组的顺序容器。

2) std::pmr::vector 是使用多态分配器的模板别名。

元素相继存储,这意味着不仅可通过迭代器,还能用指向元素的常规指针访问元素。这意味着指向 vector 元素的指针能传递给任何期待指向数组元素的指针的函数。

(C++03 起)

vector 的存储是自动管理的,按需扩张收缩。 vector 通常占用多于静态数组的空间,因为要分配更多内存以管理将来的增长。 vector 所用的方式不在每次插入元素时,而只在额外内存耗尽时重分配。分配的内存总量可用 capacity() 函数查询。额外内存可通过对 shrink_to_fit() 的调用返回给系统。 (C++11 起)

重分配通常是性能上有开销的操作。若元素数量已知,则 reserve() 函数可用于消除重分配。

vector 上的常见操作复杂度(效率)如下:

  • 随机访问——常数 O(1)
  • 在末尾插入或移除元素——均摊常数 O(1)
  • 插入或移除元素——与到 vector 结尾的距离成线性 O(n)

std::vector (对于 bool 以外的 T )满足容器 (Container) 、具分配器容器 (AllocatorAwareContainer) 、序列容器 (SequenceContainer) 、连续容器 (ContiguousContainer) (C++17 起)及可逆容器 (ReversibleContainer) 的要求。

修改器

清除内容

std::vector<T,Allocator>::clear

void clear();

(C++11 前)

void clear() noexcept;

(C++11 起)

 从容器擦除所有元素。此调用后 size() 返回零。

非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器亦被非法化。  

保持 vector 的 capacity() 不变(注意:更改容量上的标准限制在 vector::reserve 的规定中,见 [1] )。

参数

(无)

返回值

(无)

复杂度

与容器大小,即元素数成线性。

擦除元素

std::vector<T,Allocator>::erase

iterator erase( iterator pos );

(1) (C++11 前)

iterator erase( const_iterator pos );

(C++11 起)

iterator erase( iterator first, iterator last );

(2) (C++11 前)

iterator erase( const_iterator first, const_iterator last );

(C++11 起)

 从容器擦除指定的元素。

1) 移除位于 pos 的元素。

2) 移除范围 [first; last) 中的元素。

非法化位于擦除点或之后的迭代器,包含 end() 迭代器。

迭代器 pos 必须合法且可解引用。从而不能以 end() 迭代器(合法,但不可解引用)为 pos 的值。

first==last 则迭代器 first 不必可解引用:擦除空范围是无操作。

参数

pos - 指向要移除的元素的迭代器
first, last - 要移除的元素范围
类型要求
- T 必须满足可移动赋值 (MoveAssignable) 的要求。

返回值

后随最后被移除元素的迭代器。若迭代器 pos 指代最后元素,则返回 end() 迭代器。

异常

不抛出,除非 T 的赋值运算符抛异常。

复杂度

线性:调用 T 析构函数的次数与被擦除的元素数相同,调用 T 赋值运算符的次数与 vector 中被擦除元素后的元素数相等。

移除末元素

std::vector<T,Allocator>::pop_back

void pop_back();

 移除容器的最末元素。

在空容器上调用 pop_back 是未定义的。

非法化指向末元素的迭代器和引用,以及 end() 迭代器。

参数

(无)

返回值

(无)

复杂度

常数。

异常

(无)

交换内容

std::vector<T,Allocator>::swap

void swap( vector& other );

(C++17 前)

void swap( vector& other ) noexcept(/* see below */);

(C++17 起)

 将内容与 other 的交换。不在单个元素上调用任何移动、复制或交换操作。

所有迭代器和引用保持合法。尾后迭代器被非法化。

若 std::allocator_traits<allocator_type>::propagate_on_container_swap::value 为 true ,则用非成员 swap 的非限定调用交换分配器。否则,不交换它们(且若 get_allocator() != other.get_allocator() ,则行为未定义)。

(C++11 起)

参数

other - 要与之交换内容的容器

返回值

(无)

异常

(无)

(C++17 前)
noexcept 规定:  

noexcept(std::allocator_traits<Allocator>::propagate_on_container_swap::value
|| std::allocator_traits<Allocator>::is_always_equal::value)

(C++17 起)

复杂度

常数。

调用示例

#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#include <functional>
#include <time.h>
#include <vector>

using namespace std;

struct Cell
{
    int x;
    int y;

    Cell() = default;
    Cell(int a, int b): x(a), y(b) {}

    Cell &operator +=(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }

    Cell &operator +(const Cell &cell)
    {
        x += cell.x;
        y += cell.y;
        return *this;
    }

    Cell &operator *(const Cell &cell)
    {
        x *= cell.x;
        y *= cell.y;
        return *this;
    }

    Cell &operator ++()
    {
        x += 1;
        y += 1;
        return *this;
    }


    bool operator <(const Cell &cell) const
    {
        if (x == cell.x)
        {
            return y < cell.y;
        }
        else
        {
            return x < cell.x;
        }
    }

    bool operator >(const Cell &cell) const
    {
        if (x == cell.x)
        {
            return y > cell.y;
        }
        else
        {
            return x > cell.x;
        }
    }

    bool operator ==(const Cell &cell) const
    {
        return x == cell.x && y == cell.y;
    }
};

std::ostream &operator<<(std::ostream &os, const Cell &cell)
{
    os << "{" << cell.x << "," << cell.y << "}";
    return os;
}


int main()
{
    std::cout << std::boolalpha;

    std::mt19937 g{std::random_device{}()};
    srand((unsigned)time(NULL));

    auto generate = []()
    {
        int n = std::rand() % 10 + 110;
        Cell cell{n, n};
        return cell;
    };

    //3) 构造拥有 count 个有值 value 的元素的容器。
    std::vector<Cell> vector1(3, generate());
    //替换容器的内容。1) 以 count 份 value 的副本替换内容。
    std::cout << "vector1:  ";
    std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;

    //3) 构造拥有 count 个有值 value 的元素的容器。
    std::vector<Cell> vector2(5, {101, 101});
    //替换容器的内容。1) 以 count 份 value 的副本替换内容。
    std::cout << "vector2:  ";
    std::copy(vector2.begin(), vector2.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;

    //将内容与 other 的交换。不在单个元素上调用任何移动、复制或交换操作。
    //所有迭代器和引用保持合法。尾后迭代器被非法化。
    std::cout << "swap before:" << std::endl;
    std::cout << "vector1:  ";
    std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << "vector2:  ";
    std::copy(vector2.begin(), vector2.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    vector1.swap(vector2);
    std::cout << "swap after:" << std::endl;
    std::cout << "vector1:  ";
    std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << "vector2:  ";
    std::copy(vector2.begin(), vector2.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;

    //从容器擦除所有元素。此调用后 size() 返回零。
    //非法化任何指代所含元素的引用、指针或迭代器。任何尾后迭代器亦被非法化。
    //保持 vector 的 capacity() 不变
    std::cout << "clear before:" << std::endl;
    std::cout << "vector2.size():       " << vector2.size() << std::endl;
    std::cout << "vector2.data():       " << vector2.data() << std::endl;
    vector2.clear();
    std::cout << "clear after:" << std::endl;
    std::cout << "vector2.size():       " << vector2.size() << std::endl;
    std::cout << "vector2.data():       " << vector2.data() << std::endl;
    std::cout << std::endl;


    std::vector<Cell> vector3(6, generate());
    std::generate(vector3.begin(), vector3.end(), generate);
    std::cout << "vector3:  ";
    std::copy(vector3.begin(), vector3.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    //从容器擦除指定的元素。1) 移除位于 pos 的元素。
    vector3.erase(vector3.begin());
    std::cout << "iterator erase( iterator pos ) after: " << std::endl;
    std::cout << "vector3:  ";
    std::copy(vector3.begin(), vector3.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    //从容器擦除指定的元素。2) 移除范围 [first; last) 中的元素。
    vector3.erase(vector3.begin() + 1, vector3.end() - 1);
    std::cout << "iterator erase( iterator pos ) after: " << std::endl;
    std::cout << "vector3:  ";
    std::copy(vector3.begin(), vector3.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;

    //移除容器的最末元素。在空容器上调用 pop_back 是未定义的。
    //非法化指向末元素的迭代器和引用,以及 end() 迭代器。
    vector3.pop_back();
    std::cout << "vector3:  ";
    std::copy(vector3.begin(), vector3.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;

    return 0;
}

输出

猜你喜欢

转载自blog.csdn.net/qq_40788199/article/details/130463140