[转] c++11中的std::tuple元组和std::tie

功能简介

std::tuple是c++11提供的新模板类,在很多流行语言都有对应的实现,一般翻译为元组。使用它可以把多个不同类型的变量组合成一个对象。

简单示例

以下是std::tuple的简单示例(来源:https://en.cppreference.com/w/cpp/utility/tuple)

#include <tuple>
#include <iostream>
#include <string>
#include <stdexcept>

std::tuple<double, char, std::string> get_student(int id)
{
    // C++11构建tuple的写法
    if (id == 0) return std::make_tuple(3.8, 'A', "Lisa Simpson");

    // C++17提供了更方便的构建tuple的写法
    //if (id == 0) return { 3.8, 'A', "Lisa Simpson" };

    if (id == 1) return std::make_tuple(2.9, 'C', "Milhouse Van Houten");
    if (id == 2) return std::make_tuple(1.7, 'D', "Ralph Wiggum");
    throw std::invalid_argument("id");
}

int main()
{
    auto student0 = get_student(0);
    // 通过下标位置获取tuple中对应的元素
    std::cout << "ID: 0, "
              << "GPA: " << std::get<0>(student0) << ", "
              << "grade: " << std::get<1>(student0) << ", "
              << "name: " << std::get<2>(student0) << '\n';

    // 通过tie将tuple中的元素解构至多个变量中
    double gpa1;
    char grade1;
    std::string name1;
    std::tie(gpa1, grade1, name1) = get_student(1);
    std::cout << "ID: 1, "
              << "GPA: " << gpa1 << ", "
              << "grade: " << grade1 << ", "
              << "name: " << name1 << '\n';

    // C++17提供了更方便的解构写法
    //auto [ gpa2, grade2, name2 ] = get_student(2);
    //std::cout << "ID: 2, "
    //          << "GPA: " << gpa2 << ", "
    //          << "grade: " << grade2 << ", "
    //          << "name: " << name2 << '\n';
}

和struct比较

先看例子,再做比较

struct student {
  double gpa;
  char grade;
  std::string name;
};

student get_student(int id) {
  if (id == 0) {
    student s;
    s.gpa = 3.8;
    s.grade = 'A';
    s.name = "Lisa Simpson";
    return s;
  }
  // ...省略构建其余id的重复代码,只做简单演示
}

int main {
  auto student0 = get_student(0);

  std::cout << "ID: 0, "
            << "GPA: " << student0.gpa << ", "
            << "grade: " << student0.grade << ", "
            << "name: " << student0.name << '\n';
  // ...省略获取其余id的重复代码,只做简单演示
}

相比较于std::tuple,struct需要定义结构体这个复合类型。

如果单说以上所举例的这个场景,个人觉得struct的写法表意更清晰些。
原因是函数get_student所返回的gpa、grade、name三个元素变量在含义上本身是非常紧密的。
假设我们除了这个函数,还有其他地方需要同时使用这三个变量,比如update_student或print_student等,那么struct的写法将更合适些。

多说一句,作为开发,我们要保持学习新知识的习惯。但是不能有了新锤子,就看哪都是钉子。为了用新技术而用。
而应该带着新锤子,观察和思考哪有合适钉子,再合理运用。

和std::pair比较

先看例子,再做比较

std::pair<double, std::pair<char, std::string> > get_student(int id) {
  if (id == 0) {
    return std::make_pair(3.8, std::make_pair('A', "Lisa Simpson"));
  }
  // ...省略构建其余id的重复代码,只做简单演示
}

int main() {
  auto student0 = get_student(0);
  std::cout << "ID: 0, "
            << "GPA: " << student0.first << ", "
            << "grade: " << student0.second.first << ", "
            << "name: " << student0.second.second << '\n';
  // ...省略获取其余id的重复代码,只做简单演示
  return 0;
}

相比较于std::tuple,std::pair如果想要支持多于2个的变量,需要多层嵌套或结合struct使用。

std::tie的其他用法

std::tie除了第一个例子中演示的用于解构std::tuple中的元素,还可以用来将多个变量构造成std::tuple,从而做大小比较。例如 https://en.cppreference.com/w/cpp/utility/tuple/tie 中演示的例子。这种写法更modern些~

get函数

// map::find
#include <iostream>
#include <map>

int main ()
{
  std::map<char,int> mymap;
  std::map<char,int>::iterator it;

  mymap['a']=50;
  mymap['b']=100;
  mymap['c']=150;
  mymap['d']=200;

  it = mymap.find('b');
  if (it != mymap.end())
    mymap.erase (it);

  // print content:
  std::cout << "elements in mymap:" << '\n';
  std::cout << "a => " << mymap.find('a')->second << '\n';
  std::cout << "c => " << mymap.find('c')->second << '\n';
  std::cout << "d => " << mymap.find('d')->second << '\n';

  return 0;
}

输出:

elements in mymap:
a => 50
c => 150
d => 200
发布了126 篇原创文章 · 获赞 9 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/chengbeng1745/article/details/104144477