C++17结构化绑定

概述

  1. 结构化绑定是C++17引入的一种新语法,用于对元组的拆解,提高开发效率和代码可读性。
  2. 使用结构化绑定可以减少中间变量,降低程序员的命名负担。
  3. 语法格式为:auto [变量1, 变量2] = 变量,编译器会自动推导变量1和变量2的类型。
  4. 结构化绑定中的变量个数,即[]中的变量个数,必须与元组中能够拆分出的变量个数相同,且这些变量必须在当前作用域中未声明。

使用

在pair中使用

  • pair可以将两个变量组合成一个变量,而无需定义结构体或类。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
pair<int, double> p(10, 20.1);  // 创建一个包含两个元素的pair

// C++17之前获取两个变量的值
int a = p.first;  // 获取第一个元素
double b = p.second;  // 获取第二个元素
cout << a << " " << b << endl;  // 输出:10 20.1

// C++17之后使用结构化绑定
auto [x, y] = p;  // 将pair中的值分别绑定到x和y
cout << x << " " << y << endl;  // 输出:10 20.1

在tuple中使用

  • tuple可以将多个变量组合成一个变量,不局限于两个,但使用起来较为复杂。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
tuple<int, double, string> t(10, 20.1, "亮鹏");  // 创建一个包含三个元素的tuple

// C++17之前获取每个变量的值
int a = get<0>(t);  // 获取第一个元素
double b = get<1>(t);  // 获取第二个元素
string c = get<2>(t);  // 获取第三个元素
cout << a << " " << b << " " << c << endl;  // 输出:10 20.1 亮鹏

// 使用结构化绑定
auto [x, y, z] = t;  // 将tuple中的值分别绑定到x, y, 和z
cout << x << " " << y << " " << z << endl;  // 输出:10 20.1 亮鹏
  • 通过上面两个案例,可以发现结构化绑定的便捷之处。

自定义结构体中使用

  • 在结构体中也可以使用结构化绑定,结构体中声明变量的顺序与[]中变量的顺序相同。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
struct MyStruct {
    int a;
    int b;
};

// 创建结构体变量
MyStruct s = {10, 20};

// C++17之前获取每个变量的值
int a = s.a;
int b = s.b;
cout << a << " " << b << endl;  // 输出:10 20

// 使用结构化绑定
auto [x, y] = s;  // 将结构体中的值分别绑定到x和y
cout << x << " " << y << endl;  // 输出:10 20

数组中使用

  • 结构化绑定还可以用于数组,但不是很常用。
1
2
3
4
5
6
7
8
9
// 创建数组并初始化
int arr[5] = {0};
for(int i = 0; i < 5; i++) {
    arr[i] = i + 1;
}

// 使用结构化绑定
auto [a, b, c, d, e] = arr; // 数组中的元素依次绑定到变量a, b, c, d, 和e
cout << a << " " << b << " " << c << " " << d << " " << e << endl;   // 输出:1 2 3 4 5

结构化绑定的引用

  • 结构化绑定还可以与引用结合,实现对原变量值的修改。
1
2
3
4
5
6
7
pair<int, int> p(10, 20);

// 使用引用进行结构化绑定
auto& [a, b] = p;  // 通过引用绑定
b = 30;  // 修改b的值
cout << a << " " << b << endl; // 输出:10 30
cout << p.first << " " << p.second << endl;   // 输出:10 30

map的范围for中使用

  • map容器中,存储的每一个元素都是键值对,使用范围for循环遍历时可以进行结构化绑定,提高编程效率。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
// 使用map,unordered_map,multimap都可以
unordered_map<int, int> um = {
    {1, 10},
    {2, 20},
    {3, 30},
    {4, 40}
};

// C++17之前的遍历方式
for(auto kv : um) {
    cout << kv.first << " " << kv.second << endl;
}

// 使用结构化绑定的遍历方式
for(auto [k, v] : um) {  // 通过结构化绑定将键和值分别绑定到变量k和v
    cout << k << " " << v << endl;
}

元素类型为pair的vector范围遍历for

  • 如果vector容器中存储的元素类型为pairtuple,也可以使用结构化绑定简化开发。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
vector<pair<int, int>> v = {
    {1, 2},
    {3, 4},
    {5, 6}
};

// C++17之前的遍历方式
for(auto p : v) {
    cout << p.first << " " << p.second << endl;
}

// 使用结构化绑定的遍历方式
for(auto [x, y] : v) {  // 通过结构化绑定将pair中的值分别绑定到变量x和y
    cout << x << " " << y << endl;
}

注意事项

结构化绑定的嵌套

  • 在C++17中,结构化绑定不允许嵌套,否则编译不通过。以下以unordered_map为例,键为int类型,值为pair类型。
1
2
3
4
5
6
7
8
9
unordered_map<int, pair<int, int>> um = {
    {1, {2, 3}},
    {4, {5, 6}}
};

// 错误示例:结构化绑定不能嵌套
for(auto [k, [v1, v2]] : um) {
    // 编译错误
}

数组长度必须为常量

  • 从C99开始,定义数组时长度可以使用变量(MSVC编译器除外)。但是,如果要进行结构化绑定,就不能使用变量定义数组长度。
1
2
3
4
5
int n = 2;
int arr[n] = {0}; // 正确,可以使用变量定义数组

// 但是不能对使用变量定义的数组进行结构化绑定
// auto [x, y] = arr;  // 错误,数组长度必须为常量
使用 Hugo 构建
主题 StackJimmy 设计