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

news2025/2/21 19:50:16

定义于头文件<map>

template<

    class Key,
    class T,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<std::pair<const Key, T> >

> class map;
(1)
namespace pmr {

    template <class Key, class T, class Compare = std::less<Key>>
    using map = std::map<Key, T, Compare,
                         std::pmr::polymorphic_allocator<std::pair<const Key,T>>>

}
(2)(C++17 起)

 std::map 是有序键值对容器,它的元素的键是唯一的。用比较函数 Compare 排序键。搜索、移除和插入操作拥有对数复杂度。 map 通常实现为红黑树。

在每个标准库使用比较 (Compare) 概念的位置,以等价关系检验唯一性。不精确而言,若二个对象 ab 互相比较不小于对方 : !comp(a, b) && !comp(b, a) ,则认为它们等价(非唯一)。

std::map 满足容器 (Container) 、具分配器容器 (AllocatorAwareContainer) 、关联容器 (AssociativeContainer) 和可逆容器 (ReversibleContainer) 的要求。

修改器

原位构造元素

std::map<Key,T,Compare,Allocator>::emplace

template< class... Args >
std::pair<iterator,bool> emplace( Args&&... args );

(C++11 起)

 若容器中无拥有该关键的元素,则插入以给定的 args 原位构造的新元素到容器。

细心地使用 emplace 允许在构造新元素的同时避免不必要的复制或移动操作。 准确地以与提供给 emplace 者相同的参数,通过 std::forward<Args>(args)... 转发调用新元素(即 std::pair<const Key, T> )的构造函数。 即使容器中已有拥有该关键的元素,也可能构造元素,该情况下新构造的元素将被立即销毁。

没有迭代器或引用被非法化。

参数

args-要转发给元素构造函数的参数

返回值

返回由指向被插入元素,或若不发生插入则为既存元素的迭代器,和指代插入是否发生的 bool (若发生插入则为 true ,否则为 false )。

异常

若任何操作抛出异常,则此函数无效果。

复杂度

与容器大小成对数。

使用提示原位构造元素

std::map<Key,T,Compare,Allocator>::emplace_hint

template <class... Args>
iterator emplace_hint( const_iterator hint, Args&&... args );

(C++11 起)

 插入元素到尽可能靠近正好在 hint 之前的位置。原位构造元素,即不进行复制或移动操作。

准确地与提供给函数的参数相同者,再以 std::forward<Args>(args)... 转发调用元素类型( value_type ,即 std::pair<const Key, T> )的构造函数。

没有迭代器或引用被非法化。

参数

hint-指向将插入新元素到其前的位置的迭代器
args-转发给元素构造函数的参数

返回值

返回指向新插入元素的迭代器。

若因为元素已存在而失败,则返回指向拥有等价关键的既存元素的迭代器。

异常

若任何操作抛出异常,则此函数无效果(强异常保证)。

复杂度

通常与容器大小成对数,但若新元素被插入到恰于 hint 前则为均摊常数。

清除内容

std::map<Key,T,Compare,Allocator>::clear

void clear();

(C++11 前)

void clear() noexcept;

(C++11 起)

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

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

参数

(无)

返回值

(无)

复杂度

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

擦除元素

std::map<Key,T,Compare,Allocator>::erase

void erase( iterator pos );

(1)(C++11 前)

iterator erase( const_iterator pos );

(C++11 起)

iterator erase( iterator pos );

(C++17 起)

void erase( iterator first, iterator last );

(2)(C++11 前)

iterator erase( const_iterator first, const_iterator last );

(C++11 起)

size_type erase( const key_type& key );

(3)

从容器移除指定的元素。

1) 移除位于 pos 的元素。

2) 移除范围 [first; last) 中的元素,它必须是 *this 中的合法范围。

3) 移除关键等于 key 的元素(若存在一个)。

指向被擦除元素的引用和迭代器被非法化。其他引用和迭代器不受影响。

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

参数

pos-指向要移除的元素的迭代器
first, last-要移除的元素范围
key-要移除的元素关键值

返回值

1-2) 后随最后被移除的元素的迭代器。

3) 被移除的元素数。

异常

1,2) (无)

3) 任何 Compare 对象所抛的异常

复杂度

给定 map 的实例 c

1) 均摊常数

2) log(c.size()) + std::distance(first, last)

3) log(c.size()) + c.count(k)

交换内容

std::map<Key,T,Compare,Allocator>::swap

void swap( map& other );

(C++17 前)

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

(C++17 起)

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

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

Pred 对象必须可交换 (Swappable) ,并用非成员 swap 的非限定调用交换它们。

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

(C++11 起)

参数

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

返回值

(无)

异常

任何 Compare 对象交换所抛的异常。

(C++17 前)
noexcept 规定:  

noexcept(std::allocator_traits<Allocator>::is_always_equal::value
&& std::is_nothrow_swappable<Compare>::value)

(C++17 起)

复杂度

常数。

调用示例

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

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

struct myCompare
{
    bool operator()(const int &a, const int &b)
    {
        return a < b;
    }
};

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

std::ostream &operator<<(std::ostream &os, const std::pair<const int, Cell> &pCell)
{
    os << pCell.first << "-" << pCell.second;
    return os;
}

int main()
{
    auto genKey = []()
    {
        return std::rand() % 10 + 100;
    };

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

    std::map<int, Cell> map1;
    for (size_t index = 0; index < 5; index++)
    {
        //插入以给定的 args 原位构造的新元素到容器。
        map1.emplace(genKey(), generate());
        std::cout << "map1:    ";
        std::copy(map1.begin(), map1.end(),
                  std::ostream_iterator<std::pair<const int, Cell>>(std::cout, " "));
        std::cout << std::endl;
    }
    std::cout << std::endl;

    std::map<int, Cell> map2;
    for (size_t index = 0; index < 5; index++)
    {
        //插入新元素到尽可能接近恰在 hint 前的呆滞。原位构造元素,即不进行复制或移动操作。
        map2.emplace_hint(map2.begin(), genKey(), generate());
        std::cout << "map2:    ";
        std::copy(map2.begin(), map2.end(),
                  std::ostream_iterator<std::pair<const int, Cell>>(std::cout, " "));
        std::cout << std::endl;
    }
    std::cout << std::endl;

    std::cout << "after swap" << std::endl;
    //将内容与 other 的交换。不在单个元素上调用任何移动、复制或交换操作。
    map1.swap(map2);
    std::cout << "map1:    ";
    std::copy(map1.begin(), map1.end(),
              std::ostream_iterator<std::pair<const int, Cell>>(std::cout, " "));
    std::cout << std::endl;

    std::cout << "map2:    ";
    std::copy(map2.begin(), map2.end(),
              std::ostream_iterator<std::pair<const int, Cell>>(std::cout, " "));
    std::cout << std::endl;
    std::cout << std::endl;


    //从容器擦除所有元素。此调用后 size() 返回零。
    map1.clear();
    std::cout << "map1 is empty:   " << map1.empty() << std::endl;
    map2.clear();
    std::cout << "map2 is empty:   " << map2.empty() << std::endl;
    std::cout << std::endl;


    std::map<int, Cell> map3({{genKey(), generate()}, {genKey(), generate()},
        {genKey(), generate()}, {genKey(), generate()}, {genKey(), generate()}});
    //从容器移除指定的元素。1) 移除位于 pos 的元素。
    std::cout << "map3:    ";
    std::copy(map3.begin(), map3.end(),
              std::ostream_iterator<std::pair<const int, Cell>>(std::cout, " "));
    std::cout << std::endl;
    map3.erase(map3.begin());
    std::cout << "map3:    ";
    std::copy(map3.begin(), map3.end(),
              std::ostream_iterator<std::pair<const int, Cell>>(std::cout, " "));
    std::cout << std::endl;

    //从容器移除指定的元素。2) 移除范围 [first; last) 中的元素,它必须是 *this 中的合法范围。
    std::map<int, Cell>::iterator bit = map3.begin();
    std::advance(bit, 1);
    std::map<int, Cell>::iterator ait = bit;
    std::advance(ait, 2);
    map3.erase(bit, ait);
    std::cout << "map3:    ";
    std::copy(map3.begin(), map3.end(),
              std::ostream_iterator<std::pair<const int, Cell>>(std::cout, " "));
    std::cout << std::endl;


    map3.insert({{genKey(), generate()}, {genKey(), generate()}, {genKey(), generate()}});
    //从容器移除指定的元素。3) 移除关键等于 key 的所有元素。
    std::cout << "map3:    ";
    std::copy(map3.begin(), map3.end(),
              std::ostream_iterator<std::pair<const int, Cell>>(std::cout, " "));
    std::cout << std::endl;
    bit = map3.begin();
    std::advance(bit, 3);
    map3.erase(bit->first);
    std::cout << "map3:    ";
    std::copy(map3.begin(), map3.end(),
              std::ostream_iterator<std::pair<const int, Cell>>(std::cout, " "));
    std::cout << std::endl;
    return 0;
}

输出

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

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

相关文章

香港财经学院工商管理硕士(MBA)含金量

近年来&#xff0c;随着中国经济的崛起&#xff0c;越来越多的学生和从业人员开始关注MBA教育。在香港地区&#xff0c;香港财经学院的MBA项目备受瞩目&#xff0c;被誉为是该地区最具含金量的MBA项目之一。首先&#xff0c;香港财经学院作为一家优秀的商学院&#xff0c;在教学…

【C++系列P1】带上这篇基础小宝典,进发C++!(持续更新ing~)

​​​​​​​ 前言 大家好吖&#xff0c;欢迎来到 YY 滴 C系列 &#xff0c;热烈欢迎&#xff01;(持续更新ing~&#xff09;本章主要内容面向刚刚学完C语言&#xff0c;准备或正在接触C的老铁。而往往C奇多的小特性和知识点让铁铁们头晕晕脑涨涨&#xff0c;因而本章收纳了…

为什么北欧的顶级程序员数量远超中国?(续)

之前写过一篇文章《为什么北欧的顶级程序员数量远超中国&#xff1f;》&#xff0c;讲了北欧大神们开发的Linux、MySQL、Chrome V8、MineCraft、QT等优秀软件&#xff0c;分析了北欧有如此多顶级程序员的主要原因。 有位读者Ven 源 留言说&#xff0c;除了文章中教育优势&…

碳纤维单丝外径测试中的纳米分辨率激光衍射法解决方案

摘要&#xff1a;碳纤维单丝热膨胀系数是碳纤维复合材料设计、生产与可靠性和寿命评估的重要参数&#xff0c;本文针对单丝径向高温热膨胀系数测试这一难题提出了相应的解决方案。解决方案的核心内容是基于激光衍射法和高温辐射加热&#xff0c;并采用衍射轮廓拟合技术以及相应…

Dropout层的个人理解和具体使用

Dropout层的作用 dropout 能够避免过拟合&#xff0c;我们往往会在全连接层这类参数比较多的层中使用dropout&#xff1b;在训练包含dropout层的神经网络中&#xff0c;每个批次的训练数据都是随机选择&#xff0c;实质是训练了多个子神经网络&#xff0c;因为在不同的子网络中…

Linux常用命令——gzip命令

在线Linux命令查询工具 gzip 用来压缩文件 补充说明 gzip命令用来压缩文件。gzip是个使用广泛的压缩程序&#xff0c;文件经它压缩过后&#xff0c;其名称后面会多处“.gz”扩展名。 gzip是在Linux系统中经常使用的一个对文件进行压缩和解压缩的命令&#xff0c;既方便又好…

Python过滤信息,如省位中包含广东、安徽、浙江这3个省份的话,就pass,怎么破?...

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 但令心似金钿坚&#xff0c;天上人间会相见。 大家好&#xff0c;我是皮皮。 一、前言 前几天遇到了一个小问题&#xff0c;在做资料的时候&#xff0c…

7位专家齐聚openGauss Developer Day 2023云和恩墨专题论坛,共论数据库自主创新改造与技术发展...

5月26日&#xff0c;云和恩墨在「openGauss Developer Day 2023」主论坛上大放异彩&#xff08;←点此回顾主论坛精彩时刻&#xff09;&#xff0c;更是通过举办一场数据库技术创新与应用实践分论坛&#xff0c;力邀7位重量级嘉宾就数据库创新能力构建、行业应用实践和迁移替代…

SpringBoot配置文件的注入和读取

目录 1. 配置文件的作用 2. 两种配置文件的格式&#xff1a; 2.1 properties 基本语法&#xff1a; 2.1.1 写入 2.1.2 读取 执行原理 2.1.3 缺点分析 2.2 yml 基本语法&#xff1a; 2.2.1 写入&#xff08;非对象&#xff09; 2.2.3 配置对象 2.2.4 配置集合 多个配…

【Linux初阶】基础IO - 文件管理(深入理解文件描述符) | 重定向

文章目录 一、文件管理引入二、理解文件描述符三、文件描述符表四、文件描述符的分配规则五、重定向六、使用 dup2 系统调用实现重定向1.模拟实现 >&#xff08;输出&#xff09;2.模拟实现 >>&#xff08;追加&#xff09;3.模拟实现 <&#xff08;输入&#xff0…

【观察】浪潮信息:自研液环式真空CDU技术,将被动应对变为主动防御

毫无疑问&#xff0c;在“双碳”战略的大环境下&#xff0c;数据中心走向绿色低碳和可持续发展已成为“不可逆”的大趋势&#xff0c;特别是随着全国一体化大数据中心、新型数据中心等政策文件的出台、“东数西算”工程的正式启动&#xff0c;数据中心的建设规模和数量呈现出快…

老胡周刊QA微信机器人(基于ChatGPT)

背景 先做个介绍吧&#xff0c;老胡的信息周刊是我从2021-08-16创立的周刊&#xff0c;截止到目前(2023-05-29)将近两年时间&#xff0c;目前已经有92期周刊&#xff0c;中间基本没有断更过&#xff0c;一共发布资源统计如下&#xff1a; &#x1f3af; 项目 288&#x1f916; …

Ae:稳定运动

使用跟踪器 Tracker面板的稳定运动 Stabilize Motion功能&#xff0c;可通过手动添加和设置跟踪点来跟踪对象的运动&#xff0c;将获得的跟踪数据对图层本身进行反向变换&#xff0c;从而达到稳定画面的目的。 Ae菜单&#xff1a;窗口/跟踪器 Tracker 点击跟踪器面板上的“稳定…

长文教你如何正确使用ChatGPT提高学习效率!

最近 Chat GPT 很&#x1f525;&#xff0c;被大家评为无所不能的最强AI。据说&#xff0c;有百分之八十的留学生已经在用ChatGPT 来写作业了&#xff0c;因为ChatGPT真的是有问必答&#xff0c;光速回复&#xff0c;复制粘贴都没有它回答的快。 目录 Part.1 什么是ChatGPT&a…

驱动开发:内核读写内存浮点数

如前所述&#xff0c;在前几章内容中笔者简单介绍了内存读写的基本实现方式&#xff0c;这其中包括了CR3切换读写&#xff0c;MDL映射读写&#xff0c;内存拷贝读写&#xff0c;本章将在如前所述的读写函数进一步封装&#xff0c;并以此来实现驱动读写内存浮点数的目的。内存浮…

centos安装KVM

文章目录 一、centos安装KVM步骤 1. 检查硬件支持 2. 安装 KVM 相关软件包 3. 启动 libvirtd 服务 4. 设置 libvirtd 服务自启动 5. 验证 KVM 安装 二、出现问题的解决方法 1. 检查网络连接 2. 检查 DNS 解析 3. 检查软件源设置 4. 禁用 IPv6 前言 本篇主要介绍cen…

教育最大的失败,是普通家庭富养孩子

作者| Mr.K 编辑| Emma 来源| 技术领导力(ID&#xff1a;jishulingdaoli) 著名教育家马卡连柯曾说&#xff1a;“一切都给孩子&#xff0c;牺牲一切&#xff0c;甚至牺牲自己的幸福&#xff0c;这是父母给孩子最可怕的礼物。”前些天刷到一个挺扎心的视频&#xff0c;不知道算…

商业智能 (BI) 对企业中每个员工的 5 大好处

本文由葡萄城技术团队于博客园原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 众所周知&#xff0c;商业智能 (BI) 是探索企业数据价值的强大工具&#xff0c;能够帮助企业做出明智…

全网最全2W字-基于Java+SpringBoot+Vue+Element实现小区生活保障系统(建议收藏)

博主介绍&#xff1a;✌全网粉丝30W,CSDN特邀作者、博客专家、新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推…

破局35岁危机:技术人如何做好职业规划?

见字如面&#xff0c;我是军哥。 最近有一位读者工作 8 年了&#xff0c;后端做了 3 年&#xff0c;算法做了 5 年&#xff0c;换了 6/7 家公司&#xff0c;基本上每一家公司只干 1 年左右&#xff0c;换了 N 个行业&#xff0c;现在工作出现瓶颈&#xff0c;也不知道未来的路怎…