0

Given this code example:

#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;
    }
}

With the code above, the output is zero for each student.

However, if I change the code in the for loop like this:

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

Then the output is 3 for each student as expected.

Why does the first code version not work?

1 Answer 1

2

The captured student variable is a reference to a local variable therefore your lambda has undefined behaviour if called after student goes out of scope. Capture by value to prevent this problem.

The captured entry is a reference to an element in StudentList so the lambda works correctly as long as the reference is still valid within StudentList.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.