在集合内修改对象的可变成员是否安全
Is it safe to modify mutable members of objects inside sets?
我很好奇以下情况是否安全。
我有以下类定义:
class ActiveStatusEffect
{
public:
StatusEffect* effect;
mutable int ReminaingTurns;
ActiveStatusEffect() : ReminaingTurns(0)
{
}
//Other unimportant stuff down here
}
然后,我将其中一组存储在 std::set 中,如下所示:
struct ASECmp
{
bool operator ()(const StatusEffects::ActiveStatusEffect &eff1, const StatusEffects::ActiveStatusEffect &eff2)
{
return eff1.effect->GetPriority() < eff2.effect->GetPriority();
}
};
std::set<StatusEffects::ActiveStatusEffect, ASECmp> ActiveStatusEffects;
我将 RemainingTurn 标记为可变,因为我希望能够更改它而不会不断擦除/插入到集合中。 即
void BaseCharacter::Tick(Battles::BattleField &field, int ticks)
{
for (auto effect = ActiveStatusEffects.begin(); effect != ActiveStatusEffects.end();)// ++index)
{
auto next = effect;
++next;
if (effect->effect->HasFlag(StatusEffects::STATUS_FLAGS::TickEffect) && effect->ReminaingTurns > 0)
{
effect->effect->TickCharacter(*this, field, ticks);
--effect->ReminaingTurns;
}
if (effect->ReminaingTurns == 0)
{
ActiveStatusEffects.erase(effect);
}
effect = next;
}
}
我很担心,因为这似乎可能会弄乱集合中的排序,这意味着我不能保证集合将始终按 effect->GetPrority() 排序
如果这是真的,除了复制、修改、擦除然后插入我需要更改的内容之外,是否有一种安全的方法(例如没有 RemainingTurn 构成密钥的一部分)来执行此操作?
编辑:
@ildjarn - 对不起,我认为这无关紧要。它只返回存储在 StatusEffect 中的 int。该 int 保证不会在程序运行时更改。
int StatusEffect::GetPriority() const
{
return StatusPriority;
}
更改影响对象排序的数据确实会破坏关联容器的不变量,但由于ActiveStatusEffect::ReminaingTurns
不参与ActiveStatusEffect
对象的排序,因此保持其mutable
并修改其值是完全无害的。
我很担心,因为这似乎可能会弄乱集合中的排序,这意味着我不能保证集合将始终按 effect->GetPrority() 排序
这是一个std::set<StatusEffects::ActiveStatusEffect, ASECmp>
;除了ASECmp
定义的标准之外,它怎么能按任何标准进行排序?
如果你在 std::set 中更改某些东西的键,你就在未定义的行为土地上关闭了 - 就这么简单。它不仅会"弄乱排序",而且该集可能会完全停止正常工作。
如果键与实际对象无关,或者只是它的一部分,那么您应该考虑使用映射而不是集合:
std::map< int, ActiveStatusEffect > m;
ActiveStatusEffect x = create();
m[ x.effect->GetPriority ] = x; // !!!
代码的其他问题是你应该使用一些封装(用户代码不应该访问类的内部(即成员不应该是公共的)。
- 添加静态constexpr成员是否会更改结构/类的内存映射
- 内存中类位置的成员是否取决于类成员在类定义中的位置?
- 访问从联合与另一个成员集复制的联合中的一个成员是否未定义或未指定?
- POD 结构(相同类型的成员):成员是否位于连续的内存位置?
- 将结构别名为其第一个成员是否严格违反别名
- 将指针指向它的第一个成员是否违法?
- 常量指针到成员是否默认指向 int?
- 友元函数将内存分配给数组成员是否有任何限制?
- 检查成员是否在类中声明
- 给定仅包含布尔类型成员的结构的两个对象 s1 和 s2,只要 s1 的成员为 true,请检查 s2 的每个成员是否为真
- 未使用的数据成员是否占用内存
- 静态数据成员是否在所有类对象之前初始化?
- 如何检查两个元组的所有成员是否不同
- 使用之前在初始值设定项列表中初始化的成员初始化成员是否安全
- 使用enableif检查成员是否存在
- 类的成员是否可以与其类型(另一个类)命名相同的名称
- 堆分配类的成员是否在堆中自动分配
- 成员是否继承自超类的超类
- std::函数成员是否可以访问其他成员
- C++预处理器测试类成员是否存在