C++多元组tuple使用方法?你熟悉吗?快来看看吧
前言
tuple 是类似于pair的模板。每个pair的成员类型都不相同,但每个pair都恰好有两个成员。不同tuole类型的也不相同,但一个tuple可以有任意数量的成员。每个确定的tuple类型的成员数目是固定的,但一个tuple类型的成员数目可以与另一个tuple类型不同。
当我们希望将一些数据组合成单一对象,但又不想麻烦地定义一个新数据来表示这些数据时,tuple是非常有用的。
例如我们可以构造一个tuple
tuple<const char*, int>tp = make_tuple(sendPack,nSendSize);
这个tuple等价于一个结构体
struct A
{
char* p;
int len;
};
用tuple<const char*, int>tp就可以不用创建这个结构体了,而作用是一样的,是不是更简洁直观了
还有一种方法也可以创建元组,用std::tie,它会创建一个元组的左值引用。
auto tp = return std::tie(1, "aa", 2);
tp的类型实际是:
std::tuple<int&,string&, int&>
作者:良知犹存
转载授权以及围观:欢迎添加微信公众号:羽林君
tuple初印象
tuple支持如下的操作
std::tuple<T1, T2, ...TN> t; //创建一个空的tuple对象(使用默认构造),它对应的元素分别是T1和T2...Tn类型,采用值初始化。
std::tuple<T1, T2, ...TN> t2(v1, v2, ... vn); //创建一个tuple对象,它的元素分别是T1和T2 ...Tn类型; 每个成员用对应的vi进行初始化
std::tuple<T1&> t3(ref&); // tuple的元素类型可以是一个引用
像pair一样也可以通过make_tuple进行创建一个tuple对象,tuple的类型从初始值的类型推断
std::make_tuple(v1, v2);
返回t的第i个数据成员的引用:如果t是一个左值,结果是一个左值引用;否则,结果是一个右值引用。此外tuple的所有成员都是pulic的。
get<i>(t)
我们可以将tuple看作一个“快速而随意”的数据结构。
定义和初始化tuple
当我们定义一个std::tuple时,需要指出每个成员的类型。
tuple<size_t,size_t,size_t> threeD; //三个成员都被设置为0
tuple<string,vector<doble>,int ,list<int>> someVal("constans",{3.14,2.718},42,{0,1,2,3,4,5});
当我们创建一个std::tuple对象时,可以使用tuple的默认构造函数,它会对每个成员进行值初始化;也可以向上面someVal初始化一样,为每个成员提供一个初始值,此时的构造函数是explicit的,因此必须使用直接初始化方法。
tuple<size_t,size_t,size_t> htreeD = {1,2,3};
tuple<size_t,size_t,size_t> htreeD(1,2,3);
类似make_pair函数,标准库定义了make_tuple函数,我们还可以使用它来生成std::tuple对象。
auto item = mak_tuple("0-999-78345-x",3,20.00);
类似make_pair,make_tuple函数使用初始值的类型来推断tuple的类型。在上面示例中,item是一个tuple,类型为tuple<const char*,int ,double> .
访问tuple的成员
一个pair总是有两个成员,这样标准库就可以为他们命名(first和second),但是这种命名方法不适用于tuple,因为一个tuple的类型的成员数目是没有限制的。因为,tuple的成员都是未命名的。要访问一个tuple的成员,就要使用一个名为get的标准库函数模板。为了使用get,我们必须指定一个显示模板实参,它指出我们想要访问第几个成员。我们传递给get一个tuple对象,它返回指定成员的引用。
auto book = get<0>(iterm); //返回iterm的第一个成员
auto cnt = get<0>(iterm); //返回iterm的第二个成员
auto price = get<0>(iterm)/cnt; //返回iterm的第三个成员
尖括号中的值必须是一个整型常量表达式,与平时一样,我们从0开始计数,意味着get<0>是第一个成员。
如果不知道tuple准确的类型细节信息,可以用两个辅助类模板查询tuole的成员的数量和类型:
1.一个类模板,可以通过一个tuple类型初始化,它有一个名为value的public constexpr static数据类型,类型为size_t,表示给定tuple类型中成员数量
tuple_element<i,tupleType>::type
2.一个类模板,可以通过一个整型常量和一个tuple类型来初始化。它有一个名为type的public成员,表示给定tuple类型中指定的类型
tuple_size<tupleType>::value
通过这两个类模板我们可以获得我们需要的tuple变量的成员数量和类型
typedef decltype(item) trans;//trans是item的类型
size_t sz = tuple_size< trans>::value;//返回trans类型对象中成员的数量
tuple_element<1,trans>::type cnt ; // cnt 为 item第二个成员变量类型 int型
cnt = get<1>(item);
为了使用tuple_size或tuple_element,我们需要知道一个tuple对象的类型。与往常一样,确定一个对象的类型的最简单的方法就是使用decltype,在typedef decltype(item) trans;中,我们使用decltype来为item定义一个类型别名,用它来实例化这两个模板。
tuple_size有一个名为value的public static数据成员,它表示给定tuple中成员的数量。 tuple_element模板除了一个tuple类型外,还接受一个索引值。它有一个名为type的public类型成员,表示给定tuple类型中指定成员类型。类似get,tuple_element所使用的索引也是从0开始计数的。
std::tuple的关系和相等运算符的行为类似容器的对应操作。这些运算符逐对比较左侧tuple和右侧tuple的成员。只有两个tuple具有相同数量的成员时,我们才可以比较它们。而且,为了使用tuple的相等或不等运算符,对每对成员使用==运算符必须都是合法的;为了使用关系运算符,对每对成员使用 < 必须都是合法的。
关系和相等运算符:当两个tuole具有相同数量的成员且成员对应相等时,两个才tuple相同。
tuple<string,string> duo("1","2");
tuple<size_t,size_t> twoD(1,2);
bool b = (duo == twoD); // 错误,不能比较size_t 和 string
tuple<size_t,size_t,size_t> threeD(1,2,3);
b = (duo == threeD); // 错误,成员数量不同
tuple<size_t,size_t> origin(0,0);
b = (origin < twoD); // 正确:b为true
由于tuple定义了<和==运算符,我们可以将tuple序列传递给算法,并且可以在无序容器中将tuple作为关键字类型。
利用tie进行解包元素的值
如同pair一样也是可以通过tie进行解包tuple的各个元素的值。如下tuple对象有4个元素,通过tie解包将会把这4个元素的值分别赋值给tie提供的4个变量中。
int main(int argc, char **argv) {
std::tuple<std::string, int, std::string, int> tp;
tp = std::make_tuple("Sven", 25, "Shanghai", 21);
// 定义接收变量
std::string name;
std::string addr;
int ages;
int areaCode;
std::tie(name, ages, addr, areaCode) = tp;
std::cout << "Output: " << '\n';
std::cout << "name: " << name <<", ";
std::cout << "addr: " << addr << ", ";
std::cout << "ages: " << ages << ", ";
std::cout << "areaCode: " << areaCode << '\n';
return 0;
}
输出结果:
name: Sven, addr: Shanghai, ages: 25, areaCode: 21
但有时候tuple包含的多个元素时只需要其中的一个或两个元素,如此可以通过std::ignore进行变量占位,这样将会忽略提取对应的元素。可以修改上述例程:
std::tie(name, ages, std::ignore, std::ignore) = tp;
std::tuple中元素是被紧密地存储的(位于连续的内存区域),而不是链式结构。
如何遍历tuple成员
N表示tuple中的第N个元素
#include <iostream>
#include <tuple>
#include <string>
using namespace std;
template<typename Tuple, int N = std::tuple_size<Tuple>::value>
struct Printer
{
static void log(Tuple& t) {
Printer<Tuple, N - 1>::log(t);
using type = typename std::tuple_element<N - 1, Tuple>::type;
std::string ts = typeid(type).name();
type& v = std::get<N - 1>(t);
std::cout << ts << ":" << v << std::endl;
}
};
template<typename Tuple>
struct Printer<Tuple, 1>
{
static void log(Tuple& t) {
using type = typename std::tuple_element<0, Tuple>::type;
std::string ts = typeid(type).name();
type& v = std::get<0>(t);
std::cout << ts << ":" << v << std::endl;
}
};
int main() {
std::tuple<int, bool, string> t = std::forward_as_tuple(11, true, "ok");
Printer<std::tuple<int, bool, string>>::log(t);
return 1;
}
tuple做返回相关作用
使用tuple返回多个值,tuple的一个常见用途就是从一个函数返回多个值。
返回tuple的函数
tuple<int, string> fun()
{
// 用make_tuple来构造一个tuple
return make_tuple(1024, "tuple",'3');
}
使用函数返回的tuple
auto tp = fun();
auto id = std::get<0>(tp);
auto name= std::get<1>(tp);
auto num = std::get<2>(tp);
这就是我分享的C++多元组tuple,里面知识是实践过的,如果大家有什么更好的思路,欢迎分享交流哈。
—END—
推荐阅读
【1】c++nullptr(空指针常量)、constexpr(常量表达式)
【2】嵌入式底层开发的软件框架简述
【3】CPU中的程序是怎么运行起来的 必读
【4】C++的匿名函数(lambda表达式)
【5】阶段性文章总结分析
本公众号全部原创干货已整理成一个目录,公众号后台回复[ 资源 ]即可获得。
C++多元组tuple使用方法?你熟悉吗?快来看看吧的更多相关文章
- 自学Python2.3-基本数据类型-元组tuple(object) 方法
Python tuple方法总结 一.元组的简介 1.元组与列表一样,也是一种序列,但是唯一不同的元组是不能修改的 2.元组的元素不可修改,但是元组元素的元素是可以修改的 3.元组通过()括起来表示 ...
- Python 元组 tuple() 方法
描述 Python 元组 tuple() 方法用于将可迭代对象(字符串.列表.元祖.字典)转换为元组. 语法 tuple() 方法语法: tuple(iterable) 参数 iterable -- ...
- 元组tuple类型内置方法
目录 元组tuple类型内置方法 用途 定义 常用操作+内置方法 优先掌握 存一个值or多个值 有序or无序 可变or不可变 元组tuple类型内置方法 元组是不可变的列表,在定义完成后后面就不可以进 ...
- 7.4 元组tuple类型内置方法
元组tuple 元组相当于不可变的列表,在定义完成后后面就不可以进行更改,因此元组只可取不可存 因为不可变,所以相对列表来说,他的功能也少了很多,所以,不难理解,他有个优点就是占用内存小. 作用:能够 ...
- python基础-元组(tuple)及内置方法
元组-tuple 用途:用于存储多个不同类型的值,但是不能存储可变类型数据 定义方法:用小括号存储数据,数据与数据之间通过逗号分隔,元组中的值不能改变. 注意: 1.定义元组时,如果里面只有一个值,在 ...
- Python Tuple(元组) tuple()方法
描述 Python 元组 tuple() 函数将列表转换为元组.每组词 www.cgewang.com 语法 tuple()方法语法: tuple( iterable ) 参数 iterable -- ...
- Python中的元组(tuple)、列表(list)、字典(dict)
-------------------------------更新中-------------------------------------- 元组(tuple): 元组常用小括号表示,即:(),元 ...
- Java元组Tuple使用实例--转载
原文地址:http://50vip.com/35.html 一.为什么使用元组tuple? 元组和列表list一样,都可能用于数据存储,包含多个数据:但是和列表不同的是:列表只能存储相同的数据类型,而 ...
- Java元组Tuple介绍与使用
一.元组介绍 仅仅一次方法调用就可以返回多个对象,你应该经常需要这样的功能吧.可以return语句只允许返回单个对(可能有人说返回一个集合就可以了,请记住,一个集合也只是一个对象而已)因此,解决办法就 ...
随机推荐
- linux kernel操作GPIO函数
一.头文件 #include <asm/gpio.h> 二.注册 GPIO int gpio_request(unsigned gpio, const char *label) 功能:申请 ...
- 搭乘“AI大数据”快车,肌肤管家,助力美业数字化发展
经过疫情的发酵,加速推动各行各业进入数据时代的步伐.美业,一个通过自身技术.产品让用户变美的行业,在AI大数据的加持下表现尤为突出. 对于美妆护肤企业来说,一边是进入存量市场,一边是疫后的复苏期,一边 ...
- Vue基础语法与指令
项目初始化 用vscode打开终端,输入npm init -y生成package.json 然后安装vue npm install vue 需要注意的是,我遇到了这个问题 出现原因:文件夹名和生成的p ...
- CAN总线采样点测试
采样点是什么? 采样点是接受节点判断信号逻辑的位置,CAN通讯属于异步通讯.需要通过不断的重新同步才能保证收发节点的采样准确. 若采样点太靠前,则因为线缆原因,DUT外发报文尚未稳定,容易发生采样错误 ...
- 2019 Java开发利器Intellij IDEA安装、配置和使用
进入Intellij IDEA的官网,选择电脑对应的合适版本进行下载,这儿我选择的是Intellij IDEA的社区版,安装旗舰版可去网上找相应的教程. Intellij IDEA的官网:https: ...
- 【System】paging和swaping之间的区别是什么?
分析paging和swapping的区别,首先要了解内存管理 当虚拟内存用二级存储(物理磁盘)作为主存的扩展时,内核会尽力保持最活跃的数据在主存中.有一下两个内核例程做这件事情: 1.交换(swapp ...
- 【System】I/O密集型和CPU密集型工作负载之间有什么区别
CPU密集型(CPU-bound) CPU密集型也叫计算密集型,指的是系统的硬盘.内存性能相对CPU要好很多,此时,系统运作大部分的状况是CPU Loading 100%,CPU要读/写I/O(硬盘/ ...
- 设计一款兼容ST207和GD207的开发板
在MCU的学习中,大部分人都是学习别人的开发板,例如正点原子.野火等,优点是有可靠的教程和代码,缺点是容易让人有种自己全部都学会的了错觉,听了课程编写了代码,运行正常. 这个时候,可以尝试自已做一块属 ...
- 【译】Async/Await(三)——Aysnc/Await模式
原文标题:Async/Await 原文链接:https://os.phil-opp.com/async-await/#multitasking 公众号: Rust 碎碎念 翻译 by: Praying ...
- windows_myql 安装与卸载详细讲解,
windows_myql 安装 注意: 安装前把 所有杀毒软件,安全卫士等关闭. 打开下载的mysql安装文件双击解压缩,运行"mysql-5.5.40-win64.msi". 注 ...