C++ 17 结构化绑定

C++ 17 结构化绑定

C++17 引入的结构化绑定(Structured Bindings)是一个非常有用的语言特性,使得解构和访问多个值变得更加简洁和直观。结构化绑定允许你将一个对象或数据结构的多个元素绑定到独立的变量上,这在处理返回多个值的函数或解构容器时非常方便。

语法与使用场景

  1. 解构std::tuple
    在 C++17 之前,如果你有一个 std::tuple ,需要分别获取其中的元素,通常会使用 std::get:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <tuple>
    #include <iostream>

    std::tuple<int, double, std::string> getTuple() {
    return {1, 3.14, "Hello"};
    }

    int main() {
    auto t = getTuple();
    int i = std::get<0>(t);
    double d = std::get<1>(t);
    std::string s = std::get<2>(t);

    std::cout << i << ", " << d << ", " << s << '\n';
    }

    使用结构化绑定,可以将这段代码简化:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <tuple>
    #include <iostream>

    std::tuple<int, double, std::string> getTuple() {
    return {1, 3.14, "Hello"};
    }

    int main() {
    auto [i, d, s] = getTuple(); // 结构化绑定

    std::cout << i << ", " << d << ", " << s << '\n';
    }

    在这里,i、d 和 s 分别绑定到 std::tuple 的第 0、1 和 2 个元素上。

  2. 解构std::pair
    std::pair 也是结构化绑定的典型应用场景:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <utility>
    #include <iostream>

    std::pair<int, std::string> getPair() {
    return {42, "Answer"};
    }

    int main() {
    auto [num, str] = getPair(); // 结构化绑定

    std::cout << num << ", " << str << '\n';
    }
  3. 适用于数组和结构体
    结构化绑定不仅限于元组和对,还可以用于数组和结构体:

    1
    2
    3
    4
    5
    6
    7
    8
    #include <iostream>

    int main() {
    int arr[3] = {1, 2, 3};
    auto [a, b, c] = arr; // 解构数组

    std::cout << a << ", " << b << ", " << c << '\n';
    }

    对于结构体,只要结构体的成员变量是公共的且没有默认的删除构造函数,也可以使用结构化绑定:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <iostream>

    struct Point {
    int x;
    int y;
    };

    int main() {
    Point p = {10, 20};
    auto [x, y] = p; // 解构结构体

    std::cout << "x: " << x << ", y: " << y << '\n';
    }
  4. 用于std::mapstd::unordered_map这类关联容器

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <map>
    #include <iostream>

    int main() {
    std::map<int, std::string> m = {{1, "one"}, {2, "two"}, {3, "three"}};

    for (const auto& [key, value] : m) {
    std::cout << key << " -> " << value << '\n';
    }
    }

工作原理

结构化绑定实际上是一个语法糖,它在幕后生成了合适的变量并调用相应的 getter 函数(如 std::get)来初始化这些变量。这使得代码更加简洁和可读。

结论

C++17的结构化绑定是一个强大的特性,极大地简化了多值返回、数组、结构体等的解构过程,使得代码更加直观和简洁。在需要解构数据的场景中,结构化绑定可以显著提高代码的可读性和维护性