【问题标题】:Why is the boolean value within a structure within a vector not being updated?为什么向量内的结构中的布尔值没有被更新?
【发布时间】:2015-06-15 04:59:16
【问题描述】:

这听起来像是一个非常基本的问题,但我已经尝试修复一个简单的错误一个多小时了,但我似乎无法理解发生了什么。

我的头文件中有以下结构声明:

struct StudentBody
{
    string name;

    Vec2 position;

    bool disabled;

    StudentBody(string name, Vec2 position) : name(name), position(position) {}
};

这个结构被填充到一个向量类型中:

std::vector<StudentBody> students_real;

像这样:

students_real =
    {
        StudentBody("student1",Vec2(DISPLAY_WIDTH - 50, LOWER_MARGIN + 100)),
        StudentBody("student2",Vec2(DISPLAY_WIDTH - 100, LOWER_MARGIN + 100)),
        StudentBody("student3",Vec2(DISPLAY_WIDTH - 150, LOWER_MARGIN + 100)),
        StudentBody("student4",Vec2(DISPLAY_WIDTH - 200, LOWER_MARGIN + 100))
    };

默认情况下,所有学生的“已禁用”设置为 false。

然后我有一个由屏幕刷新率触发的“更新”方法,在该方法中我有以下代码:

for (auto it = students_real.begin(); it != students_real.end(); it++)
        {
            auto student_to_check = *it;

            CCLOG("student %s disabled -> %i",student_to_check.name.c_str(),student_to_check.disabled);

            if (student_to_check.name == "student1" || student_to_check.disabled) {
                continue;
            }

            bool disableStudent = true;

            //... A custom condition here checks if "disabledStudent" should become false or stay as true...

            if (disableStudent)
            {
                CCLOG("Disabling %s",student_to_check.name.c_str());

                student_to_check.disabled = true;

                CCLOG("student %s disabled -> %i",student_to_check.name.c_str(),student_to_check.disabled);
            }
        }

这里的问题是“禁用”标志没有保持为真。当我首先检查条件时,它是错误的。然后我也检查我的第二个条件,如果它满足,我将它设置为 true。但是,下次启动此 for 循环时,条件会返回 false。

这让我相信我的"auto student_to_check = *it;" 给了我一份结构的副本来处理它,而不是结构本身?或者发生了什么?为什么我不能修改向量内结构的值?

【问题讨论】:

  • auto student_to_check = *it => auto&amp; student_to_check = *it
  • 需要auto&amp; student_to_check = *it;
  • StudentBody 的构造函数不保证“默认情况下所有学生的“禁用”设置为 false”
  • 您也可以使用基于范围的 for 循环,例如:for(auto&amp;&amp; student_to_check : students_real)

标签: c++ c++11


【解决方案1】:

这个:

auto student_to_check = *it;

声明一个局部变量,它是向量中结构的副本。迭代器指向向量中的结构,所以可以使用:

auto student_to_check = it;

和:

student_to_check->disabled = true;

或更简单地访问向量结构中的任何内容。那么你就不需要局部变量了:

it->disabled = true;

更好的是使用 C++11 的基于范围的 for 循环,正如 @sp2danny 评论的那样:

for(auto& student_to_check : students_real)

student_to_check 将引用向量中的结构而不是本地副本,并且您的其余代码保持原样。

【讨论】:

  • 我想我明白你的意思,我实际上有 for(auto student_to_check : students_real) 但我有同样的行为,所以我把它改成了使用迭代器。是因为我错过了“&”吗?自动在结构上制作副本和自动&制作指针的默认行为?对于使用 auto 的对象就足够了,对吗?因为对象已经是指针了。
  • @Chiquis,是的,没有&amp; for 正在制作对象的副本。添加&amp; 使student_to_check 成为对原始对象的引用。
  • 我有另一个结构是“Vector students;”这是大写 V,因为它是自定义 cocos2dx 向量,但它与 std::vector 基本相同,在这种情况下为“for (auto it = Student::students.begin(); it != Student::students.end( ); it++) { auto student = *it; //...修改代码... } 正确吗?(如果我想修改它,因为它是指针向量而不是结构向量)
  • 是的,或者再次使用基于范围的 for 循环:for(auto student : students)。这次复制指针就可以了。
  • 当你删除某些项目时,一定要按照惯用的方式,即if(shouldDelete) it=students.erase(it); else ++it;,不要在for循环中更新it
猜你喜欢
  • 2020-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-07
  • 1970-01-01
  • 2016-04-02
  • 1970-01-01
相关资源
最近更新 更多