2011-05-20 93 views
5

我很好奇以下情況是否安全。修改組內對象的可變成員是否安全?

我有下面的類定義:

class ActiveStatusEffect 
{ 
public: 
    StatusEffect* effect; 
    mutable int ReminaingTurns; 
    ActiveStatusEffect() : ReminaingTurns(0) 
    { 
    } 
    //Other unimportant stuff down here 
} 

我然後存儲一組這些一個std ::裏面設置如下:

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; 

我標誌着作爲RemainingTurns可變因爲我想能夠改變它而不需要不斷地擦除/插入集合。即

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

我很擔心,因爲它這似乎可能搞亂集內的排序,這意味着我不能保證集將始終效應 - 排序> GetPrority()

如果這是真的,有沒有一種安全的方式(如沒有RemainingTurns組成的關鍵),除了複製,修改,擦除,然後插入我需要改變?

編輯:

@ildjarn - 對不起,我沒想到的是重要的。它只是返回一個存儲在StatusEffect中的int值。該int保證不會改變程序的運行時間。

int StatusEffect::GetPriority() const 
{ 
    return StatusPriority; 
} 
+0

聽起來像是['的std :: priority_queue <>'](HTTP的情況下://www.sgi的.com /技術/ STL/priority_queue.html)容器代替;對於更復雜的情況,請參見[升壓多指標(http://www.boost.org/doc/libs/1_37_0/libs/multi_index/doc/index.html ) – sehe 2011-05-20 06:28:27

+0

@sehe:可以事先ity處理更改密鑰而不重新插入? – 2011-05-20 06:30:40

+2

當我們看不到'StatusEffect :: GetPriority()'的實現時,我們怎麼可能知道'RemainingTurns''可變性是否很重要? – ildjarn 2011-05-20 06:30:47

回答

6

影響的對象將打破的確關聯容器的不變量的排序,但由於ActiveStatusEffect::ReminaingTurns不參與ActiveStatusEffect對象的任何排序,保持mutable並修改它的值更改數據是完全無害的。

我很擔心,因爲它這似乎可能搞亂集內的排序,這意味着我不能保證集將始終效應 - 排序> GetPrority()

這是一個std::set<StatusEffects::ActiveStatusEffect, ASECmp>;除了ASECmp定義的標準之外,它如何排序呢?

+0

我擔心它打破了關鍵,未來的插入沒有被插入正確地發生一次 – Megatron 2011-05-20 07:04:55

+0

@ user127817:但是,對於標準的有序關聯容器而言,「ActiveStatusEffect :: ReminaingTurns」並不是密鑰身份的一部分,因爲它在「ActiveStatusEffect」排序中沒有考慮到。也就是說,你在將來打破某些事情的唯一風險是通過改變'ActiveStatusEffect'的排序邏輯來以某種方式使用'ReminaingTurns'。 – ildjarn 2011-05-20 17:23:22

2

如果您更改std :: set中的某個鍵的關鍵字,那麼您將在Undefined Behavior land中關閉 - 就像那樣簡單。它不僅會「搞亂順序」,而且該設置可能會停止正常工作。

0

如果關鍵是無關的實際對象,或者只是它的一部分,那麼你應該考慮使用地圖,而不是一組:

std::map< int, ActiveStatusEffect > m; 
ActiveStatusEffect x = create(); 
m[ x.effect->GetPriority ] = x;  // !!! 

與您的代碼的其他問題是,你應該使用一些封裝(用戶代碼不應該訪問類的內部(即,成員不應公開)

相關問題