2017-01-01 39 views
0

圖可以表示爲鄰接矩陣或鄰接表。我的Graph對象將圖形表示爲鄰接矩陣。出於性能原因,除非要求,否則我不計算鄰接列表;然而,一旦請求,我想保留清單(以避免重新構建它)。「適時計算」適合用於可變嗎?

將鄰接列表mutable做成合適的,以便用戶可以生成否則爲constGraph對象的鄰接列表?我問,因爲我不相信建立鄰接矩陣將被視爲「物理」,而不是對「Graph」狀態的「邏輯」改變。我也有一個adjacencyListBuilt方法,所以建立鄰接表不是「不可見的」(見https://isocpp.org/wiki/faq/const-correctness#mutable-data-members)。

如果我理解正確,聲明adjacencyList實例變量mutable將允許任何方法更新它。有沒有辦法只有buildAdjacencyList方法能夠修改const對象上的adjacencyList實例變量?

+1

對你最後一個問題 - 呃,不要用任何其他方法觸摸它。你是這個類的作者,沒有人扭動你的手臂來修改'buildAdjacencyList'之外的'adjacencyList'。 –

+1

'adjacencyListBuilt'的用途是什麼?來電者希望如何使用這些信息?這聽起來像暴露了一個應該與調用者無關的實現細節。把它拿出來,使用'mutable'作爲getAdjacencyList()結果緩存的成員變得非常合理。 –

+0

'adjacencyListBuilt'只用在'assert'語句中。每次調用getAdjacencyList'時,我都不會檢查列表是否已經建立,而是依賴程序員在需要時建立它。 (是的,我知道刪除這個檢查的好處是非常小的。) – Zack

回答

7

使用mutable緩存從內部成員計算的結果是適當的。請注意,它可能會破壞線程安全。

但我也會考慮一個單獨的類或函數,對const對象執行計算。

1

「即時計算」正是mutable的發明,因此是的,它是一個合適的用途。請注意,界面不會專門請求構建它;你只需要就可以訪問,班級會注意到它還沒有建成,並且在「幕後」建立它。因此邏輯狀態而不是會受到影響。

如果您正在考慮一個函數來請求建築物,然後是一個函數或一組訪問函數,這些函數或函數在建築還沒有被請求時無效,那麼您就錯了。請注意,問題將出現在接口上,而不是在實現上;因此不管你是否使用mutable來實現它都是錯誤的。

關於如何進一步保護它不受其他方法影響的問題:如果我理解正確,那麼只有兩件事情應該對鄰接列表進行處理:或者應該從當前的鄰接矩陣計算出來,或者它應該失效。因此,我建議把它封裝到一個單獨的類中(私有的Graph類),它封裝了可變成員(並且本身被用作非可變成員變量),並且只提供兩個操作:(1)訪問關聯矩陣( const函數,計算列表如果還沒有計算)和(2)使列表無效(非const,因爲只有對圖的改變才能使列表無效)。這樣,Graph類的任何const成員函數都不能修改該列表。

2

有沒有一種方法,只有buildAdjacencyList方法能夠修改const對象上的adjacencyList實例變量?

當然,使用嵌套的私有成員和friend

class myGraph; 
void buildAdjacencyListImpl(const myGraph&); 

class myGraph 
{ 
    class myAdjacencyListCache 
    { 
     mutable realAdjacencyList cached_list; 

     friend void buildAdjacencyListImpl(const myGraph&); 
    } adj_list; 
    friend void buildAdjacencyListImpl(const myGraph&); 

    void buildAdjacencyList() const { buildAdjacencyListImpl(*this); } 
}; 

void buildAdjacencyListImpl(const myGraph& g) 
{ 
    realAdjacencyList& listToBuild = g.adj_list.list_cache; 
    // it isn't const, and can be modified 
} 
1

事實證明,在我的具體情況,有這麼多不同的緩存值,這使事情可變拿到總非常快。 (上面的描述被簡化了。)相反,我決定製作兩個不同版本的GraphImmutableGraphMutableGraphImmutableGraph沒有方法添加或刪除邊和頂點;因此,在ImmutableGraph應宣佈爲const的情況很少。