Menu
CoddyTech

结构化绑定

本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 88 课,共 104 课。

C++17 引入的结构化绑定,可以让你在一条声明中将数组、对、元组或结构体中的多个值解包为单独命名的变量。处理复合数据时,这能让代码更简洁易读。

语法使用 auto,方括号中包含新的变量名:

#include <iostream>
#include <map>
#include <tuple>

int main() {
    // 解包 pair
    std::pair<std::string, int> person{"Alice", 25};
    auto [name, age] = person;
    std::cout << name << " is " << age << "\n";
    
    // 解包元组
    std::tuple<int, double, char> data{42, 3.14, 'X'};
    auto [num, pi, letter] = data;
    
    // 在基于范围的 for 循环中解包
    std::map<std::string, int> scores{{"Bob", 90}, {"Carol", 85}};
    for (const auto& [student, score] : scores) {
        std::cout << student << ": " << score << "\n";
    }
}

结构化绑定也适用于数组和具有公有成员的自定义结构体:

struct Point {
    double x;
    double y;
};

Point getOrigin() { return {0.0, 0.0}; }

int main() {
    auto [x, y] = getOrigin();
    
    int arr[3] = {1, 2, 3};
    auto [a, b, c] = arr;
}

你可以使用 auto& 或 const auto& 按引用绑定,避免复制,并在需要时修改原始值。这个特性在迭代 STL 容器或处理返回多个值的函数时尤其有用。

challenge icon

挑战

简单

让我们构建一个学生成绩分析器,展示结构化绑定的强大之处。你将创建一个处理学生记录和课程数据的系统,并在代码中使用结构化绑定,简洁地解包键值对、元组和结构体。

你需要将代码组织在三个文件中:

  • Student.h:定义一个 Student 结构体,其中包含学生姓名(std::string)、ID(int)和 GPA(double)的公有成员。再创建一个名为 createStudent 的函数,它接收姓名、ID 和 GPA,并返回一个 Student 结构体。
  • GradeUtils.h:创建用于处理成绩的工具函数。

    定义一个 getGradeInfo 函数,它接收一个数字成绩(整数),并返回一个包含三个值的 std::tuple:字母等级(std::string)、绩点(double)以及是否及格(bool)。使用以下评分标准:

    • 90 及以上:“A”,4.0,true
    • 80 到 89:“B”,3.0,true
    • 70 到 79:“C”,2.0,true
    • 60 到 69:“D”,1.0,true
    • 低于 60:“F”,0.0,false

    再定义一个 makeScorePair 函数,它接收课程名称(std::string)和成绩(int),并返回由这两个值组成的 std::pair。

  • main.cpp:读取四个输入:
    1. 学生姓名(字符串)
    2. 学生 ID(整数)
    3. 课程名称(字符串)
    4. 成绩(整数)

    在主函数中使用结构化绑定:

    1. 使用姓名、ID 和占位 GPA 0.0 调用 createStudent。使用结构化绑定将返回的结构体解包为单独的变量,然后打印:Student: [name] (ID: [id])
    2. 使用课程名称和成绩调用 makeScorePair。使用结构化绑定解包这个键值对,然后打印:Course: [course], Score: [score]
    3. 使用成绩调用 getGradeInfo。使用结构化绑定解包元组中的三个元素,然后打印:
      Grade: [letter]
      Points: [points]
      Passing: [yes/no]
      (及格时打印 "yes",不及格时打印 "no")

例如,输入 Alice、1001、Math 和 85 时:

Student: Alice (ID: 1001)
Course: Math, Score: 85
Grade: B
Points: 3
Passing: yes

输入 Bob、2002、Physics 和 55 时:

Student: Bob (ID: 2002)
Course: Physics, Score: 55
Grade: F
Points: 0
Passing: no

记得在需要的地方包含 <tuple> 和 <utility>。关键在于,结构化绑定可以让你通过一条清晰易读的声明,将复合类型、键值对、元组和结构体解包为具名变量。

亲手试试

#include <iostream>
#include <string>
#include "Student.h"
#include "GradeUtils.h"

int main() {
    // 读取输入
    std::string studentName;
    int studentId;
    std::string courseName;
    int score;
    
    std::cin >> studentName;
    std::cin >> studentId;
    std::cin >> courseName;
    std::cin >> score;
    
    // TODO: 用姓名、ID 和占位 GPA 值 0.0 调用 createStudent
    // 使用结构化绑定解包结构体:auto [name, id, gpa] = ...
    // 输出:Student: [name] (ID: [id])
    
    
    // TODO: 用课程名称和分数调用 makeScorePair
    // 使用结构化绑定解包 pair:auto [course, sc] = ...
    // 输出:Course: [course], Score: [score]
    
    
    // TODO: 用分数调用 getGradeInfo
    // 使用结构化绑定解包元组:auto [letter, points, passing] = ...
    // 输出:
    // Grade: [letter]
    // Points: [points]
    // Passing: [yes/no](如果 passing 为 true,输出 "yes";否则输出 "no")
    
    
    return 0;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C++ 在线编译器