lambda returns 变量在 lambda 内部初始化时的值不正确,但如果在外部范围内初始化则不正确

lambda returns incorrect values when variable is initialised inside lambda but not if initialised in outer scope

鉴于此代码示例:

#include <vector>
#include <cstdint>
#include <memory>
#include <iostream>
#include <functional>

enum StudentType { BURSARY, PAYING };

class Student {
public:
    Student(const std::vector<int>& grades, StudentType type) : m_grades(grades), m_type(type) {}

    uint8_t gradeByIndex(size_t index) { return m_grades[index]; }
    StudentType getType() { return m_type; }
    size_t numGrades() { return m_grades.size(); }

private:
    std::vector<int> m_grades;
    StudentType m_type;
};


int main() {

    std::vector<int> grades1{ 1,2,3 };
    std::vector<int> grades2{ 4,5,6 };
    std::vector<int> grades3{ 7,8,9 };
    std::vector<int> grades4{ 10,11,12 };
    std::vector<int> grades5{ 13,14,15 };

    using func = std::function<std::unique_ptr<Student>()>;

    std::vector<func> funcs;

    using StudentGradesAndType = std::pair<std::vector<int>, StudentType>;

    const StudentGradesAndType StudentList[]{ {grades1, BURSARY},
                                 {grades1, BURSARY},
                                 {grades1, PAYING},
                                 {grades1, PAYING},
                                 {grades1, PAYING} };


    for (auto& entry : StudentList)
    {
        Student student(entry.first, entry.second);
        auto mylambda = [&student]() {
            return std::make_unique<Student>(student);
        };

        funcs.push_back(mylambda);
    }

    for (auto el : funcs) {
        std::cout << el()->numGrades() << std::endl;
    }
}

使用上面的代码,每个学生的输出为零。

但是,如果我像这样更改 for 循环中的代码:

for (auto& entry : StudentList)
{
    auto mylambda = [&entry]() {
        Student student(entry.first, entry.second);
        return std::make_unique<Student>(student);
    };
    funcs.push_back(mylambda);
}

那么每个学生的输出都是 3。

为什么第一个代码版本不起作用?

捕获的 student 变量是对局部变量的引用,因此如果在 student 超出范围后调用,您的 lambda 具有未定义的行为。按值捕获以防止此问题。

捕获的 entry 是对 StudentList 中元素的引用,因此只要引用在 StudentList.

中仍然有效,lambda 就可以正常工作