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

news2024/11/17 11:48:51
定义于头文件 <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;
}

 输出

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/504492.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

adb bugreport 与adb shell getprop 详解

&#x1f604;作者简介&#xff1a; 小曾同学.com,一个致力于测试开发的博主⛽️&#xff0c; 如果文章知识点有错误的地方&#xff0c;还请大家指正&#xff0c;让我们一起学习&#xff0c;一起进步。&#x1f60a; 座右铭&#xff1a;不想当开发的测试&#xff0c;不是一个好…

低代码行业未来如何?大家都真的看好低代码开发吗?

低代码行业未来如何&#xff1f;大家都真的看好低代码开发吗&#xff1f; 是否一定需要开发人员&#xff1f;低代码和无代码平台会取代传统编程吗&#xff1f;低代码/无代码真的是未来吗&#xff1f; 无疑是需要且重要的。今天就来解答为什么低/零代码工具越来越受欢迎&#xf…

第1章计算机系统漫游

文章目录 1、信息就是位上下文2、程序被其他程序翻译成不同的格式3、了解编译系统如何工作的益处4、处理器读并解释储存在存储器中的指令4.1 系统的硬件组成4.2 执行 hello 程序 5、高速缓存6、形成层次结构的存储设备7、操作系统管理硬件7.1 进程7.2 线程7.3 虚拟存储器7.4 文…

领英退出中国,谷歌Bard集成进安卓,陆奇最新演讲,HuggingFace网传遭禁|今日科技圈要闻

夕小瑶科技说 原创 作者 | 智商掉了一地、兔子酱 AI 新闻速递来咯&#xff01;搬好小板凳&#xff0c;一起了解近期发生了什么新鲜事~ 领英职场退出中国 领英是一个专注于职业发展、招聘和营销等方面的社交平台。Linkdein 官方公众号发布公告称&#xff0c;由于面临日趋激烈的…

Spring MVC——Rest风格

REST&#xff08;Representational State Transfer&#xff09; 当我们想表示一个网络资源的时候&#xff0c;可以使用两种方式: 我们分别用查询id为1的用户信息与保存用户信息举例传统风格资源描述形式 http://localhost/user/getById?id1http://localhost/user/saveUser RES…

第五届河南省CCPC河南省省赛题解+复盘

第五届河南省CCPC河南省省赛题解复盘 今年省赛相当有意思的一点&#xff0c;是20级第一次线下省赛&#xff0c;对于部分队也可能是最后一次&#xff0c;看队名就能看出来很多 考研就业的选手&#xff0c;一群老年人在这PK&#xff0c;氛围挺不错。 A - 小水獭游河南 — 签到 …

代码随想录算法训练营day28 | 93.复原IP地址,78.子集,90.子集II

代码随想录算法训练营day28 | 93.复原IP地址&#xff0c;78.子集&#xff0c;90.子集II 93.复原IP地址解法一&#xff1a;回溯 78.子集解法一&#xff1a;回溯&#xff08;单独处理空集&#xff09;解法二&#xff1a;回溯&#xff08;统一处理空集&#xff09; 90.子集II解法一…

Linux网络编程:socket、客户端服务器端使用socket通信(TCP)

socket socket&#xff08;套接字&#xff09;&#xff0c;用于网络中不同主机间进程的通信。 socket是一个伪文件&#xff0c;包含读缓冲区、写缓冲区。 socket必须成对出现。 socket可以建立主机进程间的通信&#xff0c;但需要协议&#xff08;IPV4、IPV6等&#xff09;…

NeurIPS 2022 | 正则化分子构象场

编译 | 于洲 今天我们介绍来自复旦大学的Lihao Wang以及其他来自字节跳动AI实验室与清华大学AI产业研究院的成员发布在NeurIPS 2022会议上的工作&#xff0c;该文章介绍了一种新方法——正则化分子构象场&#xff08;RMCF&#xff09;&#xff0c;用于从化学结构中预测最有利的…

为什么聊天机器人界面不是未来

​ 0-1之间有无限多种状态 比如&#xff1a;0 按时上下班&#xff0c;用固定时间长度获取价值1 创业&#xff0c;用非线性时间&#xff0c;获取真实价值0-1 之间有无限多种状态 shadow ChatBot目前的交互界面有非常多值得被改进的体验机会。最近看到一篇非常有启发性的文章&…

【JY】浅析基于性能的抗震分析方法——性能设计

【写在前文】 在阅读此文前&#xff0c;可先看下以下文章&#xff1a; 【JY】基于性能的抗震设计&#xff08;一&#xff09; 【JY】基于性能的抗震设计&#xff08;二&#xff09; 【JY|理念】结构概念设计之(设计理念进展) 【性能设计】 建筑结构通常使用弹性分析进行抗震设计…

ProbTransformer:应对RNA折叠等自然过程数据模糊的神秘力量

编译 | 于洲‍ 今天我们介绍来自德国弗赖堡大学计算机科学系的Jrg K.H. Franke, Frederic Runge以及Frank Hutter发表在NeurIPS 2022会议上的工作&#xff0c;该文章介绍了一种新颖的基于概率的神经网络架构ProbTransformer&#xff0c;它是Transformer生态系统的一种层级增强&…

wangzherongyao PMO

感谢【五一节】大家的相遇&#xff0c;总结下。 2023年05月02日&#xff0c;【第一组】组队开黑 我总结了下这天为什么打的那么好&#xff0c;首先赛季初段位在王者附近&#xff0c;大家心态重视程度也高&#xff0c;不轻敌&#xff0c;也不盲目&#xff0c;运营好兵线一步一步…

springboot2集成knife4j(swagger3)

springboot2集成knife4j&#xff08;swagger3&#xff09; springboot2集成knife4j&#xff08;swagger3&#xff09; 环境说明集成knife4j 第一步&#xff1a;引入依赖第二步&#xff1a;编写配置类第三步&#xff1a;放行相关资源 & 保证启动了knife4j第四步&#xff1a…

Lecture 14:Life-long Learning

目录 Catastrophic Forgetting 灾难性遗忘(Catastrophic Forgetting)的克服之道 Selective Synaptic Plasticity Additional Neural Resource Allocation Memory Reply 其他 Catastrophic Forgetting ——为什么今日的人工智慧无法成为天网&#xff1f;灾难性遗忘 Life…

将ssh发布密钥添加到服务器的ssh授权密钥中,但是为什么我仍然无法ssh登录到此服务器?

我已经将ssh发布密钥添加到服务器的ssh授权密钥中&#xff0c;但是为什么我仍然无法ssh登录到此服务器&#xff1f; 即使将ssh公钥添加到服务器的授权密钥中&#xff0c;您也可能无法通过SSH登录到服务器&#xff0c;这有几个原因: 1.服务器的authorized_keys文件的权限不正确…

DAY 56 MySQL数据库的索引

索引的概念 索引是一个排序的列表&#xff0c;在这个列表中存储着索引的值和包含这个值的数据所在行的物理地址&#xff08;类似于c语言的链表通过指针指向数据记录的内存地址&#xff09;。 使用索引后可以不用扫描全表来定位某行的数据&#xff0c;而是先通过索引表找到该行…

专业的媒体邀约服务

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 媒体邀约是什么&#xff1f;专业的媒体邀约服务包含哪些内容&#xff1f;怎么选择合适的媒体邀约服务机构&#xff1f; 今天胡老师就跟大家分享下这方面你的经验。 一&#xff0c;媒体邀约…

【Java入门合集】第四章继承(三)

【Java入门合集】第四章继承&#xff08;三&#xff09; 博主&#xff1a;命运之光专栏&#xff1a;JAVA入门 学习目标 1.掌握继承性的主要作用、实现、使用限制&#xff1b; 2.掌握this和super的含义及其用法&#xff1b; 3.掌握方法覆写的操作&#xff1b; 4.掌握final关键字…

【Spring MVC】Web程序开发

文章目录 1. 什么是Spring MVC&#xff1f;2. 如何创建Spring MVC项目&#xff1f;3. 简单示例演示4. 路由接口映射4.1 RequestMapping4.2 GetMapping和PostMapping 5. 获取参数5.1 获取单个参数5.2 获取多个参数5.3 获取对象5.4 RequestParam参数重命名5.5 ResquestBody接收JS…