【问题标题】:lambda returns incorrect values when variable is initialised inside lambda but not if initialised in outer scope当变量在 lambda 内部初始化时,lambda 返回不正确的值,但如果在外部范围内初始化则不会
【发布时间】:2021-04-11 17:38:49
【问题描述】:

鉴于此代码示例:

#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。

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

【问题讨论】:

    标签: c++ lambda scope


    【解决方案1】:

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

    捕获的entry 是对StudentList 中元素的引用,因此只要引用在StudentList 中仍然有效,lambda 就可以正常工作。

    【讨论】:

      猜你喜欢
      • 2021-07-08
      • 1970-01-01
      • 1970-01-01
      • 2013-04-05
      • 2016-03-11
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 2013-02-13
      相关资源
      最近更新 更多