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

void push_back( const T& value );

(1)

void push_back( T&& value );

(2) (C++11 起)

后附给定元素 value 到容器尾。

1) 初始化新元素为 value 的副本。

2) 移动 value 进新元素。

若新的 size() 大于 capacity() ,则所有迭代器和引用(包含尾后迭代器)都被非法化。否则仅尾后迭代器被非法化。

参数

value - 要后附的元素值
类型要求
- 为使用重载 (1) , T 必须满足可复制插入 (CopyInsertable) 的要求。
- 为使用重载 (2) , T 必须满足可移动插入 (MoveInsertable) 的要求。

返回值

(无)

复杂度

均摊常数。

异常

若抛出异常(可能因为 Allocator::allocate() 或元素复制/移动构造函数/赋值),则此函数无效果(强异常保证)。

T 的移动构造函数不是 noexcept 且 T 不可复制插入 (CopyInsertable) 到 *this ,则 vector 将使用会抛出的移动构造函数。若它抛出,则抛弃保证且效果未指定。 (C++11 起)

注意

一些实现在 push_back 导致会超出 max_size 的重分配时亦抛出 std::length_error ,由于这会隐式调用 reserve(size()+1) 的等价者。

在容器末尾就地构造元素

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

template< class... Args >
void emplace_back( Args&&... args );

(C++11 起)
(C++17 前)

template< class... Args >
reference emplace_back( Args&&... args );

(C++17 起)

添加新元素到容器尾。元素通过 std::allocator_traits::construct 构造,它典型地用布置 new 于容器所提供的位置原位构造元素。参数 args... 以 std::forward<Args>(args)... 转发到构造函数。

若新的 size() 大于 capacity() ,则所有迭代器和引用(包含尾后迭代器)都被非法化。否则仅尾后迭代器被非法化。

参数

args - 转发到元素构造函数的参数
类型要求
- value_type 必须满足可移动插入 (MoveInsertable) 和 可就位构造 (EmplaceConstructible) 的要求。

返回值

(无)

(C++17 前)

到被插入元素的引用。

(C++17 起)

复杂度

均摊常数。

异常

若抛出异常,则此函数无效果(强异常保证)。 若 T 的移动构造函数非 noexcept 且非可复制插入 (CopyInsertable) 到 *this ,则 vector 将使用抛出的移动构造函数。若它抛出,则保证被舍弃,且效果未指定。

注意

因为可能发生再分配, emplace_backvector 要求元素类型为可移动插入 (MoveInsertable) 。

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

调用示例

#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;
    };

    //1) 默认构造函数。构造拥有默认构造的分配器的空容器。
    std::vector<Cell> vector1;
    while (vector1.size() < 3)
    {
        //后附给定元素 value 到容器尾。1) 初始化新元素为 value 的副本。
        vector1.push_back(generate());
        std::cout << "vector1:  ";
        std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
        std::cout << std::endl;
    }

    while (vector1.size() < 6)
    {
        //后附给定元素 value 到容器尾。2) 移动 value 进新元素。
        Cell cell = generate();
        vector1.push_back(std::move(cell));
        std::cout << "vector1:  ";
        std::copy(vector1.begin(), vector1.end(), std::ostream_iterator<Cell>(std::cout, " "));
        std::cout << std::endl;
    }
    std::cout << std::endl;


    //1) 默认构造函数。构造拥有默认构造的分配器的空容器。
    std::vector<Cell> vector2;
    while (vector2.size() < 3)
    {
        int n = std::rand() % 10 + 110;
        //添加新元素到容器尾。元素通过 std::allocator_traits::construct 构造,
        //它典型地用布置 new 于容器所提供的位置原位构造元素。
        //参数 args... 以 std::forward<Args>(args)... 转发到构造函数。
        vector2.emplace_back(n, n);
        std::cout << "vector2:  ";
        std::copy(vector2.begin(), vector2.end(), std::ostream_iterator<Cell>(std::cout, " "));
        std::cout << std::endl;
    }
    return 0;
}

猜你喜欢

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