《白话C++》第10章 Page34 10.2.6 std::pair和tuple

std::pair

在“泛型”一章,曾动手写过“Pair”,相当于自造了一个轮子,

因为C++标准库提供了类似的实现:std::pair。pair提供一对成员,两个成员的类型分别通过模板参数指定,比如:

#include <utility> /**< 包含pair及关系比较小工具 */

......

std::pair <int, std::string> num_name;
num_name.first = 10;
num_name.second = "Tom";

std::pair <std::string, double> name_price;
name_price.first = "Apple";
name_price.second = 4980.00;

//也支持在构造时直接初始化:
std::pair <int, double> tmp(10, 2.3);

pair在标准库中一个典型的应用,就是作为std:map容器内部存储的元素

map容器可称为“映射表”或“键值对”,它的每一个元素都由两个成员组成,第一个成员作为“KEY”,第二个成员称为“(VALUE)值”。

map容器会在内部根据“(KEY)键”对元素进行排序。用户通过“KEY”快速找到元素,而用户实际需要的,往往是“VALUE”的内容。通过“pair”结构,用户可以幸福美满而简单地实现在一起。

std::tuple

std::tuple支持让0个,1个,以及多个数据“捆绑”在一起。其中0个和1个没多大意义,2个则可以找“std::pair”,所以应从3个说起。

#include <tuple>
......
std::tuple <int, string, double> t3(100, "table", 89.20);

构造对象和pair一致,但入和取出这其中三个成员就很不相同了,first  second  third ……这样的思路,

tuple提供成员函数“get <int> ()”来访问内部成员数据:

int score = t3.get<0>();
string name = t3.get<1>();
double price = t3.get<2>();

一旦一个turple由模板出一个类型(class),则这个class又会拥有一个成员模板函数,大致长这个样子(示意代码):

template <int Index>
T const& get <int Index> () const
{
    ...
}

既然这是一个函数模板,那么当传入的Index值不同,就会生成不同的函数,也就是说:get<0>()get<1>()是两个不同的函数。

一个“3-tuple”的类,会有三个get<int>()函数,这是在编译时,就决定下来的,所以对例中的“t3”对象,不能幻想可以调用它的第4个访问元素:

t3.get<3>();

这个错误不需要等到运行期爆发,编译器就会报错。

正是因为需要在编译器就生成具体的函数(模板->函数),所以上例才能做到,每一个get<>(),都已经有一个明确的返回值了,它可不像any需在运行期去猜与试

比如对于t3, get <0>()返回的是int,get <2>()返回的是double,错不了。

正因为是需要在编译期就生成具体的函数(模板->函数),所以也不能幻想给get传一个变量,期望在运行期再决定取哪个成员:

int i
cin >> i;
??? = t3.get <i> ();//错

想要循环输出一个tuple内部的各个成员,这样看似朴素的梦想,也破灭了:

for(int i = 0; i < 3; ++i)
    cout << t3.get<i>();

想象以下,如果要制造一个“10-tuple”的对象,光写它的类型名称,就有够长的了,所以stl分别提供了make_tuple和make_pair函数,方便我们直接造出一个tuple或pair对象。假设我们有一个map:

std::map <int, double> a_map;

要万里面添加成员(pair对象),方法一:

std::pair <int, string> pair_1(10, 0.1);
a_map.insert(pair_1);

方法二,使用make_pair函数:

a_map.insert(std::make_pair(10, 0.1));

当然,对于map,也可以使用:“a_map[10] = 0.1;”。make_tuple函数用法和make_pair类似:

make_tuple(10, 0.2); //生成一个tuple<int, double>对象

//生成一个tuple<string(), vector <string>>对象,
//俩成员的值都是各自类型的默认构造的初始化值:
make_tuple(string(), vector <string> ());

//可以嵌套:
make_tuple(100, "ABC", 12.3, make_tuple(10, 0.4));

最后,无论是pair还是tuple,都支持保存一个对象的引用(而非复制品):

int i = 100;
std::pair <int&, double> tmp2(i, 0.0);
++ tmp2.first;
cout << i << endl;

不过,如果要使用make_pair()函数生成一个pair<int&, double>对象,如何写呢?下面的代码实现不了:

int i = 10;
pair <int &, double> tmp = make_pair(i, 1.2);

这段代码编译不能通过,make_pair函数生成的对象类型是 pair<int, double>, 而不是tmp类型, 这就需要学习STL提供的“引用”小工具 。

  • 21
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值