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 就可以正常工作
鉴于此代码示例:
#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
.