当前位置:   article > 正文

C++:std::tuple使用说明_std::tuple性能比较差

std::tuple性能比较差

目录

一、如何创建std::tuple

二、std::tuple中的元素是在堆中创建的还是在栈中创建的

三、如何获取std::tuple中存放的元素个数

四、如何获取std::tuple中存放的元素类型

五、如何遍历std::tuple中的元素

六、如何通过已有的std::tuple生成新的std::tuple

七、如何将std::tuple转化为对象

八、如何将std::tuple中的元素拆解


一、如何创建std::tuple

主要有如下4种方式:

  • std::tuple<>()
  • std::forward_as_tuple()
  • std::make_tuple()
  • std::tie()
  1. #include <iostream>
  2. #include <tuple>
  3. #include <string>
  4. using namespace std;
  5. static int cnt = 0;
  6. class Person {
  7. private:
  8. int id;
  9. public:
  10. string name;
  11. int age;
  12. Person() {
  13. id = ++cnt;
  14. cout << "Person()" << id <<endl;
  15. }
  16. Person(string _name, int _age): name(_name), age(_age) {
  17. id = ++cnt;
  18. cout << "Person(string _name, int _age)" << id << endl;
  19. }
  20. Person(const Person&) {
  21. id = ++cnt;
  22. cout << "Person(const Person&)" << id << endl;
  23. }
  24. Person(Person&&) {
  25. id = ++cnt;
  26. cout << "Person(Person&&)" << id << endl;
  27. }
  28. Person& operator=(const Person&) {
  29. cout << "operator=(const Person&)" << id << endl;
  30. return *this;
  31. }
  32. };
  33. int main () {
  34. {
  35. cout << "--------------------------------//(1)" << endl;
  36. tuple<int, bool, string, Person> t1 = tuple<int, bool, string, Person>(11, true, "ok", Person("ok", 11));
  37. }
  38. {
  39. cout << "--------------------------------//(2)" << endl;
  40. Person p("ok", 11);
  41. tuple<int, bool, string, Person> t2 = tuple<int, bool, string, Person>(11, true, "ok", p);
  42. }
  43. {
  44. cout << "--------------------------------//(3)" << endl;
  45. tuple<int, bool, string, Person> t3 = std::forward_as_tuple(11, true, "ok", Person("ok", 11));
  46. }
  47. {
  48. cout << "--------------------------------//(4)" << endl;
  49. Person p("ok", 11);
  50. tuple<int, bool, string, Person> t4 = std::forward_as_tuple(11, true, "ok", p);
  51. }
  52. {
  53. cout << "--------------------------------//(5)" << endl;
  54. tuple<int, bool, string, Person> t5 = std::make_tuple(11, true, "ok", Person("ok", 11));
  55. }
  56. {
  57. cout << "--------------------------------//(6)" << endl;
  58. Person p("ok", 11);
  59. tuple<int, bool, string, Person> t6 = std::make_tuple(11, true, "ok", p);
  60. }
  61. {
  62. cout << "--------------------------------//(7)" << endl;
  63. int i = 11;
  64. bool b = true;
  65. string s = "ok";
  66. Person p("ok", 11);
  67. tuple<int, bool, string, Person> t7 = std::tie(i, b, s, p);
  68. }
  69. return 1;
  70. }

 执行结果如下:

--------------------------------//(1)
Person(string _name, int _age)1
Person(Person&&)2
--------------------------------//(2)
Person(string _name, int _age)3
Person(const Person&)4
--------------------------------//(3)
Person(string _name, int _age)5
Person(Person&&)6
--------------------------------//(4)
Person(string _name, int _age)7
Person(const Person&)8
--------------------------------//(5)
Person(string _name, int _age)9
Person(Person&&)10
Person(Person&&)11
--------------------------------//(6)
Person(string _name, int _age)12
Person(const Person&)13
Person(Person&&)14
--------------------------------//(7)
Person(string _name, int _age)15
Person(const Person&)16

 从执行结果可以看到,(1)(3)的效率最高,(2)(4)(7)次之,(5)更低,(6)最差。也就是说,尽量使用std::tuple<>()和std::forward_as_tuple()通过内部元素使用右值引用构造的形式;尽量不要使用std::make_tuple()的任何形式。

二、std::tuple中的元素是在堆中创建的还是在栈中创建的

std::tuple中的元素创建的区域是跟std::tuple创建的区域相同。如果std::tuple是在栈上创建的,则其中的元素也是在栈中创建的;如果std::tuple是在堆中创建的,则其中的元素也在堆中创建。

三、如何获取std::tuple中存放的元素个数

  1. template<typename Tuple>
  2. int getSize() {
  3. return std::tuple_size<Tuple>::value;
  4. };

四、如何获取std::tuple中存放的元素类型

  1. template<typename Tuple, int N>
  2. struct TypeGetter
  3. {
  4. using type = typename std::tuple_element<N, Tuple>::type;
  5. };

N表示tuple中的第N个元素

五、如何遍历std::tuple中的元素

  1. #include <iostream>
  2. #include <tuple>
  3. #include <string>
  4. using namespace std;
  5. template<typename Tuple, int N = std::tuple_size<Tuple>::value>
  6. struct Printer
  7. {
  8. static void log(Tuple& t) {
  9. Printer<Tuple, N - 1>::log(t);
  10. using type = typename std::tuple_element<N - 1, Tuple>::type;
  11. std::string ts = typeid(type).name();
  12. type& v = std::get<N - 1>(t);
  13. std::cout << ts << ":" << v << std::endl;
  14. }
  15. };
  16. template<typename Tuple>
  17. struct Printer<Tuple, 1>
  18. {
  19. static void log(Tuple& t) {
  20. using type = typename std::tuple_element<0, Tuple>::type;
  21. std::string ts = typeid(type).name();
  22. type& v = std::get<0>(t);
  23. std::cout << ts << ":" << v << std::endl;
  24. }
  25. };
  26. int main() {
  27. std::tuple<int, bool, string> t = std::forward_as_tuple(11, true, "ok");
  28. Printer<std::tuple<int, bool, string>>::log(t);
  29. return 1;
  30. }

 执行结果:

int:11
bool:1
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >:ok

 上述代码通过定义结构体模板Printer,并对Printer做偏特化实现对tuple对象的遍历的。

六、如何通过已有的std::tuple生成新的std::tuple

主要有以下4种形式:

  • 拷贝
  • 转移
  • 交换
  • 函数返回
  1. tuple<int, bool, string, Person> swapTest() {
  2. {
  3. cout << "--------------------------------//(1)" << endl;
  4. tuple<int, bool, string, Person> t0(11, true, "ok", Person("ok", 11));
  5. cout << "--------------------------------" << endl;
  6. tuple<int, bool, string, Person> t1 = t0; // equal to tuple<int, bool, string, Person> t1(t0);
  7. }
  8. {
  9. cout << "--------------------------------//(2)" << endl;
  10. tuple<int, bool, string, Person> t0(11, true, "ok", Person("ok", 11));
  11. cout << "--------------------------------" << endl;
  12. tuple<int, bool, string, Person> t1 = move(t0); // equal to tuple<int, bool, string, Person> t1(move(t0));
  13. }
  14. {
  15. cout << "--------------------------------//(3)" << endl;
  16. tuple<int, bool, string, Person> t0(11, true, "ok", Person("ok", 11));
  17. cout << "--------------------------------" << endl;
  18. tuple<int, bool, string, Person> t1;
  19. cout << "--------------------------------" << endl;
  20. t1.swap(t0); // equal to std::swap(t1, t0);
  21. }
  22. cout << "--------------------------------//(4)" << endl;
  23. tuple<int, bool, string, Person> t0(11, true, "ok", Person("ok", 11));
  24. cout << "--------------------------------" << endl;
  25. return t0;
  26. }
  27. int main() {
  28. tuple<int, bool, string, Person> t = swapTest();
  29. cout << "--------------------------------" << endl;
  30. return 1;
  31. }

运行结果:

----------------------------------------------------------------//(1)
Person(string _name, int _age)1
Person(Person&&)2
--------------------------------
Person(const Person&)3
----------------------------------------------------------------//(2)
Person(string _name, int _age)4
Person(Person&&)5
--------------------------------
Person(Person&&)6
----------------------------------------------------------------//(3)
Person(string _name, int _age)7
Person(Person&&)8
--------------------------------
Person()9
--------------------------------
Person(Person&&)10
operator=(const Person&)9
operator=(const Person&)8
----------------------------------------------------------------//(4)
Person(string _name, int _age)11
Person(Person&&)12
--------------------------------
Person(Person&&)13
--------------------------------

 从运行结果中可以看到,(2)(4)效率最高,元素都是采用转移构造函数创建的,(1)次之,(3)最差。当然(3)性能最差是有原因,它毕竟是交换,需要双向赋值。

七、如何将std::tuple转化为对象

可以使用T make_from_tuple(Tuple&& t)(C++17),并且对象要的一个类型和顺序与std::tuple中元素的类型和顺序相同的构造函数。

八、如何将std::tuple中的元素拆解

1.拆解成可变参数函数

  1. //void print()
  2. //{
  3. // cout << endl;
  4. //}
  5. //
  6. //template <typename HeadType, typename... Types >
  7. //void print(HeadType arg, Types... Args)
  8. //{
  9. // cout << typeid(HeadType).name() << ":" << arg << endl;
  10. //
  11. // print(Args...);
  12. //}
  13. template < typename Tuple, typename... Types >
  14. constexpr void tuple_element_type(Tuple&& t, Types... Args)
  15. {
  16. // print(Args...);
  17. }
  18. template<typename Tuple, std::size_t... I>
  19. constexpr void tuple_element_index(Tuple&& t, std::index_sequence<I...>)
  20. {
  21. tuple_element_type(t, std::get<I>(std::forward<Tuple>(t))...);
  22. }
  23. template <typename Tuple>
  24. constexpr void break_tuple(Tuple&& t)
  25. {
  26. tuple_element_index(t, std::make_index_sequence<std::tuple_size_v<std::remove_reference_t<Tuple>>>{});
  27. }

最终,将std::tuple中的元素拆解到方法void tuple_element_type(Tuple&& t, Types... Args)中。

2.拆解成变量

  1. int main() {
  2. std::tuple<int, std::string, bool> t(121, "dds", true);
  3. int i;
  4. std::string s;
  5. bool b;
  6. std::tie(i, s, b) = t;
  7. cout << "i=" << i << endl;
  8. cout << "s=" << s << endl;
  9. cout << boolalpha << "b=" << b << endl;
  10. return 0;
  11. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/305964
推荐阅读
相关标签
  

闽ICP备14008679号