C++11时代的标准库快餐教程(1) - 不同类型值组成的简单列表

不同类型值组成的简单列表 - pair和tuple

值对儿,就是由两个或以上的不同类型的值,组成的简单列表结构。强调不同类型,是因为同类型用数组不就是了么。
最简单的值对,是只有两个值的对儿,这种结构叫做std::pair.

两个值结对儿-std::pair

这种简单的结构有什么用呢?答案就在于简单。
我们有很多种情况下,需要的就是简单。
1. key-value组合: 比如我们要在真正的容器里放键-值对(key-value),这是一个再普通不过的需求了。这时肯定犯不上为每一种这样的组合写一个新类,更不值得用更复杂的容器,能有一个非常简单的值对模板类是最方便的。
2. 函数返回值:C程序员可能非常羡慕其他语言,比如Go语言或很多脚本语言,返回值可以返回多个值。最常用的用法就是,先返回一个错误码,然后才是真正的返回值。

在C++模板库里,也确实就是这么做的。
针对第一种情况,C++标准库中的map结构,如map和multimap的每一个元素,都是pair对象。
而要返回多于一个值的时候,比如Set的insert函数,就返回一个pair

pair的构造

最简单的pair构造法,就是使用make_pair函数:

    auto test1 = std::make_pair(1,"test1");
    auto test2 = std::make_pair(2,"test2");

C++11的auto关键字发挥功力了,我们甚至都不需要写std::pair的模板定义,直接用std::make_pair去构造,类型请auto自己去推断。

我们再来个函数返回值的:

std::pair<int,std::string> checkValue(int value){
    if(value<1000){
        return std::make_pair(0, "checked pass");
    }else{
        return std::make_pair(-1, "checked failed");
    }
}

pair的使用

pair很简单,通过pair.first和pair.second就可以访问对象的第一个值和第二个值。
例,处理下我们上面例子的函数返回值:

    auto result = checkValue(100);
    if(result.first==0){
        std::cout << "Checked pass! The message is: "<<result.second <<"\n";
    }

三个以上的值: std::tuple

pair只能用于两个值,但是有时候我们需要多于两个值怎么办?这时候C++11又送了一份大礼给我们,C++11支持模板参数不指定具体个数个参数。所以C++98只能支持10个参数的限制再也没有了,现在的tuple可以支持多个参数。
std::get<0>这样的语法在pair时显得多余,但是推广到tuple上,它就可以大显身手了。

一句话说tuple,就是把pair的两个参数扩展成三个以上就可以了。
比如我们想在函数返回值里再多加几个值,把pair换成tuple,make_pair换成make_tuple,其余都照旧就是了。

std::tuple<int, std::string, std::string,int> checkValueWithDetails(int value){
    if(value<1000){
        return std::make_tuple(0,"checking passed","normal case",value);
    }else{
        return std::make_tuple(-1,"checking failed","bad case",value);
    }
}

返回值使用的时候,还是get<>()函数。当然这时候first和second已经没什么意义了,统一用get<>():

    auto result3 = checkValueWithDetails(1);
    if(std::get<0>(result3)==0){
        std::cout<< "Checking passed! The message is: "<<std::get<1>(result3) << "The detail info is:" << std::get<2>(result3)<<"\n";
    }

std::tie 批处理

我们想把tuple的值取出来赋到各个变量中去,一个一个get<>太麻烦,有没有办法一次性搞定?
当然有啦,我们通过std::tie函数来做这个事情:

    auto result4 = checkValueWithDetails(-1);
    int resultValue;
    std::string message;
    std::string details;
    int initValue;
    std::tie(resultValue,message,details,initValue)=result4;

写起来是不是有种在用脚本语言的感觉?
如果其中有些值我们不关注,那就用std::ignore来占位,就像Go语言中的"_"一样,就不用再定义个无用的变量了。比如上例,假如我们对message不感兴趣,我们就这么写:

    std::tie(resultValue,std::ignore,details,initValue)=result4;

std::ignore可以适用于任何类型。

好啦,快餐教程就讲这么多。
我们复习一下:
1. std::pair是C++98就有的功能,std::tuple是TR1新增的。C++11的两个特性为pair和tuple带来很大帮助,一个是auto的类型推断可以帮助我们少写代码,二是C++11支持变参数的模板,使得理论上可以支持任意多个数量的参数。tuple来自boost库,但是没有C++11支持的boost::tuple和TR1的std::tuple支持的参数个数是受限的。
2. 通过std::make_pair和std::make_tuple可以方便地构造pair和tuple对象。
3. std::tie()函数可用于将pair或tuple中的值绑定到一些变量上,不关心的值可以用std::ignore来忽略。

时间: 2025-01-30 02:05:37

C++11时代的标准库快餐教程(1) - 不同类型值组成的简单列表的相关文章

C++11时代的标准库快餐教程(2) - STL概览

STL概览 在进入STL的世界之前,我们先对其中的主要组件做一个鸟瞰: 先来一张层次图: 如果觉得层次图看不清的话,我们把它重新绘成思维导图吧: 从图中我们可以看到: STL的核心只有三个大组件: 容器 迭代器 算法 当然,这么大的一个包罗万象的C++标准库,还是有很多其他的组件,比如智能指针.字符串.正则表达式.流式I/O.并发处理等不是跟容器相关的.但是做为核心的容器库,就只有这三大组件. 容器的种类其实蛮少的,大体上分为基本容器和特殊容器两大类. 基本容器按照无序,有序,排序分成了三大类:

C++11时代的标准库快餐教程(3) - 排序

排序 讲完容器之后,我们迅速进入到算法部分. 首先看一下,我们这讲在整个算法大图的中位置: 在进入排序相关之前,我们把虽然与排序无关,但是也有关联的计数和最大值最小值部分先看一下.算是对算法部分作个预热,将来会广泛出场的lambda表达式也先借机会亮亮相. 计数 计数的目的,是数一数,在容器里,符合某一条件的元素有多少个. 算法1: std::count,数一数跟这个值相等的对象有多少个. 我们看一个例子,数数vector中有几个1: std::vector<int> bit_containe

C++11时代的标准库快餐教程(4) - 排序算法的应用

排序算法的应用 用排序做集合运算 - 子集,交集,并集与差集 上一节我们讲了排序算法,包括快速排序sort,堆排序partial_sort和归并排序stable_sort.并且讲了排序的第一个用法,二分法差找. 二分法是针对一个排序后的容器的用法,如果是多个有序容器,我们就可以快速地在其基础上进行集合的求子集,交集,并集与差集等运算. 我们还是先看一下图,排序相关算法都有哪些内容: 子集std::includes std::includes算法用于判断第一个迭代器是否包含第二个迭代器中的所有元素

musl 0.7.11发布 基于标准库Linux系统

musl是一个基于标准库Linux系统的实现.它是轻量级的,快速,简单,自由,并努力在标准上保持一致性和安全意识.它包括一个建设项目对musl在系统的标准库(如glibc)的地方,从而有可能立即评估库,建立与它小巧的静态链接二进制文件. musl 0.7.11共享库和动态加载(dlopen/dlsym)现在支持通过一个集成的近乎零开销的动态链接器.其他新功能包括POSIX消息队列,posix_spawn的search.h接口,random()PRNG,环境和浮点操作.中度严重的几个字符串和宽字符

Python模块和标准库的使用教程

#!/usr/bin/env python # coding=utf-8 lang = "python" 引入模块 >>> import sys >>> sys.path.append("~/Documents/VBS/StartLearningPython/2code/pm.py") >>> import pm >>> pm.lang 'python' 当Python解释器读取了 .py 文件

Python标准库11 多进程探索 (multiprocessing包)

原文:Python标准库11 多进程探索 (multiprocessing包) 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢!   在初步了解Python多进程之后,我们可以继续探索multiprocessing包中更加高级的工具.这些工具可以让我们更加便利地实现多进程.   进程池 进程池 (Process Pool)可以创建多个进程.这些进程就像是随时待命的士兵,准备执行任务(程序).一个进程池中可以容纳多个待命的士兵.

c++11标准库thread的问题

问题描述 c++11标准库thread的问题 上面的代码我是想实现简单的操作系统中的线程调度问题.可是出现这样的输出结果,这是为什么?我打印的字符串不是我对应数组中字符串,这和thread什么有关? 解决方案 我这里给每个线程分配的参数不知道为什么变成了一样的 解决方案二: 先看线程函数传递的参数是否都是一样的.然后就是线程函数中是否都是相同

C++11快餐教程(1)-通过using定义类型的别名

C++11快餐教程(1)-通过using定义类型的别名 在C/C++中,我们经常通过typedef来定义类型的别名. 例如: typedef unsigned char u1; typedef unsigned short u2; 但是,这样定义有一点不好,新定义的别名是放在后面的.一般我们都是通过别名找原名,从后往前找还是不方便的. 那么,我们把别名定义在前面好不好? using u4 = uint32_t; using u8 = uint64_t; 在C++11中,using不再只是用于us

简明Python3教程 16.标准库

简介 python标准库作为python标准安装的一部分,其自身包含数量庞大的实用模块, 因此熟悉python标准库非常重要,因为很多问题都能利用python标准库快速解决. 下面我们将研究标准库中的一些常用模块.完整的标准库模块列表可以在安装python时附带的文档中的'Library Reference'一节找到. 现在就让我们来看看这些模块吧.   提示 如果你感觉本章内容对于你过于超前,那么可以跳过本章.但是当你熟悉python编程后我强烈建议你把这章补上.   sys模块 sys模块包