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>::insert

iterator insert( iterator pos, const T& value );

(1) (C++11 前)

iterator insert( const_iterator pos, const T& value );

(C++11 起)

iterator insert( const_iterator pos, T&& value );

(2) (C++11 起)

void insert( iterator pos, size_type count, const T& value );

(3) (C++11 前)

iterator insert( const_iterator pos, size_type count, const T& value );

(C++11 起)

template< class InputIt >
void insert( iterator pos, InputIt first, InputIt last);

(4) (C++11 前)

template< class InputIt >
iterator insert( const_iterator pos, InputIt first, InputIt last );

(C++11 起)

iterator insert( const_iterator pos, std::initializer_list<T> ilist );

(5) (C++11 起)

 插入元素到容器中的指定位置。

1-2) 在 pos 前插入 value

3) 在 pos 前插入 valuecount 个副本。

4) 在 pos 前插入来自范围 [first, last) 的元素。

InputIt 为整数类型,则此重载与重载 (3) 拥有相同效果。 (C++11 前)
此重载仅若 InputIt 足以为遗留输入迭代器 (LegacyInputIterator) 才参与重载决议,以避免与重载 (3) 有歧义。 (C++11 起)

firstlast 是指向 *this 中的迭代器,则行为未定义。

5) 在 pos 前插入来自 initializer_list ilist 的元素。

若新 size() 大于旧 capacity() 则导致重分配。 若新的 size() 大于 capacity() ,则所有迭代器和引用都被非法化。否则,仅在插入点前的迭代器和引用保持合法。尾后迭代器亦被非法化。

参数

pos - 将内容插入到其前的迭代器。 pos 可为 end() 迭代器
value - 要插入的元素值
first, last - 要插入的元素范围,不能是指向调用 insert 所用的容器中的迭代器
ilist - 要插入的值来源的 initializer_list
类型要求
- 为使用重载 (1) , T 必须满足可复制赋值 (CopyAssignable) 和 可复制插入 (CopyInsertable) 的要求。
- 为使用重载 (2) , T 必须满足可移动赋值 (MoveAssignable) 和 可移动插入 (MoveInsertable) 的要求。
- 为使用重载 (3) , T 必须满足可复制赋值 (CopyAssignable) 和 可复制插入 (CopyInsertable) 的要求。
- 为使用重载 (4,5) , T 必须满足可就位构造 (EmplaceConstructible) 的要求。
- 为使用重载 (4) , T 必须满足可移动赋值 (MoveAssignable) 和 可移动插入 (MoveInsertable) 的要求。仅若 InputIt 满足遗留输入迭代器 (LegacyInputIterator) 但不满足遗留向前迭代器 (LegacyForwardIterator) 才要求。(C++17 前)
- 为使用重载 (4,5) , T 必须满足可交换 (Swappable) 、 可移动赋值 (MoveAssignable) 、 可移动构造 (MoveConstructible) 和 可移动插入 (MoveInsertable) 的要求。(C++17 起)

返回值

1-2) 指向被插入 value 的迭代器。

3) 指向首个被插入元素的迭代器,或若 count==0 则为 pos

4) 指向首个被插入元素的迭代器,或若 first==last 则为 pos

5) 指向首个被插入元素的迭代器,或若 ilist 为空则为 pos

复杂度

1-2) 常数,加上 pos 与容器结尾的距离成线性。

3) 与 count 成线性,加上 pos 与容器结尾的距离成线性。

4) 与 std::distance(first, last) 成线性,加上 pos 与容器结尾的距离成线性。

5) 与 ilist.size() 成线性,加上 pos 与容器结尾的距离成线性。

异常

若在尾端插入单个元素时抛出异常,且 T 为可复制插入 (CopyInsertable) 或 std::is_nothrow_move_constructible<T>::value 为 true ,则无效果(强异常保证)。

原位构造元素

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

template< class... Args >
iterator emplace( const_iterator pos, Args&&... args );

(C++11 起)

直接于 pos 前插入元素到容器中。通过 std::allocator_traits::construct 构造元素,它典型地用布置 new 在容器所提供的位置原位构造元素。将参数 args... 作为 std::forward<Args>(args)... 转发给构造函数。

若新的 size() 大于 capacity() ,则所有迭代器和引用都被非法化。否则,仅在插入点前的迭代器和引用保持合法。尾后迭代器亦被非法化。

参数

pos - 将构造新元素到其前的迭代器
args - 转发给元素构造函数的参数
类型要求
- T (容器元素类型) 必须满足可移动赋值 (MoveAssignable) 、 可移动插入 (MoveInsertable) 和 可就位构造 (EmplaceConstructible) 的要求。

返回值

指向被安置的元素的迭代器。

复杂度

pos 和容器尾的距离成线性。

异常

若 value_type 的复制构造函数、移动构造函数、赋值运算符或移动赋值运算符以外的操作抛异常,或若在用 emplace 在尾部插入单个元素时抛异常,且 value_type 为可复制插入 (CopyInsertable) 或可不抛出移动构造,则无效果(强异常保证)。

否则,效果未指定。

注意

特化 std::vector<bool> 在 C++14 前无 emplace() 成员。

调用示例

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

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(1, 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;

    //插入元素到容器中的指定位置。1-2) 在 pos 前插入 value 。
    Cell cell = generate();
    std::cout << "iterator insert( iterator pos, const T& value ) : " << std::endl;
    vector1.insert(vector1.begin(), cell);
    std::cout << "vector1.insert(vector1.begin(), Cell" << cell << " ) " << std::endl;
    std::cout << "vector1:  ";
    std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;

    //插入元素到容器中的指定位置。1-2) 在 pos 前插入 value 。
    cell = generate();
    std::cout << "iterator insert( const_iterator pos, const T& value ) : " << std::endl;
    vector1.insert(vector1.cbegin(), cell);
    std::cout << "vector1.insert(vector1.cbegin(), Cell" << cell << " ) " << std::endl;
    std::cout << "vector1:  ";
    std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;

    //插入元素到容器中的指定位置。1-2) 在 pos 前插入 value 。
    cell = generate();
    std::cout << "iterator insert( const_iterator pos, T&& value ) : " << std::endl;
    vector1.insert(vector1.cbegin(), std::move(cell));
    std::cout << "vector1.insert(vector1.cbegin(), std::move(Cell" << cell << " )) " << std::endl;
    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(2, generate());
    //替换容器的内容。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;

    //插入元素到容器中的指定位置。3) 在 pos 前插入 value 的 count 个副本。
    cell = generate();
    std::cout << "void insert( iterator pos, size_type count, const T& value ): " << std::endl;
    vector2.insert(vector2.begin(), 2, cell);
    std::cout << "vector2.insert(vector2.begin(), 2, Cell" << cell << " ) " << 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;

    //插入元素到容器中的指定位置。3) 在 pos 前插入 value 的 count 个副本。
    cell = generate();
    std::cout << "void insert( const_iterator pos, size_type count, const T& value ): " << std::endl;
    vector2.insert(vector2.cbegin(), 2, cell);
    std::cout << "vector2.insert(vector2.cbegin(), 2, Cell" << cell << " ) " << 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;

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

    //插入元素到容器中的指定位置。4) 在 pos 前插入来自范围 [first, last) 的元素。
    std::cout << "template< class InputIt >" << std::endl;
    std::cout << "void insert( iterator pos, InputIt first, InputIt last)" << std::endl;
    vector3.insert(vector3.begin(), vector1.begin(), vector1.end());
    std::cout << "vector3.insert(vector3.begin(), vector1.begin(), vector1.end())" << 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;

    std::vector<Cell> vector4;
    //插入元素到容器中的指定位置。4) 在 pos 前插入来自范围 [first, last) 的元素。
    std::cout << "template< class InputIt >" << std::endl;
    std::cout << "void insert( const_iterator pos, InputIt first, InputIt last)" << std::endl;
    vector4.insert(vector4.begin(), vector1.begin(), vector1.end());
    std::cout << "vector4.insert(vector4.begin(), vector1.begin(), vector1.end())" << std::endl;
    std::cout << "vector4:  ";
    std::copy(vector4.begin(), vector4.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;

    std::vector<Cell> vector5;
    //插入元素到容器中的指定位置。5) 在 pos 前插入来自 initializer_list ilist 的元素。
    std::cout << "void insert( const_iterator pos, std::initializer_list<T> ilist )" << std::endl;
    vector5.insert(vector5.begin(), {
   
   {101, 102}, {103, 104}, {105, 106}});
    std::cout << "vector5.insert(vector5.begin(), {
   
   {101, 102}, {103, 104}, {105, 106}})" << std::endl;
    std::cout << "vector5:  ";
    std::copy(vector5.begin(), vector5.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;


    //直接于 pos 前插入元素到容器中。
    //通过 std::allocator_traits::construct 构造元素,
    //它典型地用布置 new 在容器所提供的位置原位构造元素。
    std::vector<Cell> vector6;
    std::cout << "template< class... Args >" << std::endl;
    std::cout << "iterator emplace( const_iterator pos, Args&&... args )" << std::endl;
    std::cout << "vector6.emplace(vector6.begin(),"
              << "std::rand() % 10 + 110, std::rand() % 10 + 110)" << std::endl;
    while (vector6.size() < 6)
    {
        vector6.emplace(vector6.begin(), std::rand() % 10 + 110, std::rand() % 10 + 110);
    }
    std::cout << "vector6:  ";
    std::copy(vector6.begin(), vector6.end(), std::ostream_iterator<Cell>(std::cout, " "));
    std::cout << std::endl;
    return 0;
}

 输出

猜你喜欢

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