2011-12-30 51 views
6

如果你需要在D中重寫下面的C++代碼,你會怎麼做?如何重寫在D中使用mutable的C++代碼?

struct A{ 

    const S* _s; 
    B _b; 
    C _c; 
    mutable C _c1, _c2; 

    A(const B& b, const C& c, const S* s){ /*...*/ } 

    void compute(const R& r) const 
    { 
     //... 
     _c1 = ... 
     _c2 = ... 
    } 
}; 

d沒有mutable,而且,根據我的經驗,它很少用C++使用。但是,假設mutable在這裏用於正確的理由,我在D中有什麼選擇?

+0

這是一個類似的問題:http://stackoverflow.com/questions/4219600/logical-const-in-d – 2011-12-30 10:50:11

回答

3

有三個選項來處理這個:

  1. 丟掉const。這會使編譯器拉大,但不能保證你的代碼能按預期工作。特別是,如果你從多個線程的同一個對象上調用該函數,那麼你就處於數據競賽的擺佈之中。

  2. 使用外部數據結構來存儲可變對象:

    struct A 
    { 
        static C[const(A)*] _c1s, _c2s; 
    
        void compute(ref const(R) r) const 
        { 
         _c1s[&this] = ... 
         _c2s[&this] = ... 
        } 
    } 
    

    我使用&this爲關鍵,以外部哈希表,但你可能會更好使用某種獨特的ID 。這是一個非常醜陋和棘手的解決方案。我不喜歡它。另外,還要注意的是,哈希表是線程局部的,所以同一個對象會在不同的線程不同的值。這可能也爲您的特定應用可能不理想。

  3. 反思const如何在D.

    在d使用const,是傳遞和位即邏輯常量不被支持。這樣做的目的是保證不會發生併發共享數據寫入。即使你的代碼可能是邏輯常量正確的,它仍然將打破,如果兩個線程試圖調用同一對象上compute,所以d不允許它,並且不提供法律逃逸(無mutable)。

    實質上,只有當它們是按位const時,才應該將函數標記爲const

    這樣做的結果是,你應該在d比在C會使用const少了很多++,因爲你需要按位const的少了很多比你需要的邏輯常量。

    作爲一個例子,考慮一個簡單的(無意義的)通用equal功能,告訴你,如果兩個對象相等:

    bool equal(T)(T lhs, T rhs) { return lhs == rhs; } 
    

    注意,我沒有標明函數的參數爲​​const。這是有意的。測試的平等不應該需要按位常量 - 它只需要邏輯常量,所以強制D對對象的const級別將是不必要的限制。

    正如jA_cOp所說,D社區在D中看不到有邏輯常量的空間,無論好壞。當你嘗試像C++的const那樣使用D的const時,問題就出現了。它們不一樣,所以不要以相同的方式使用它們!如果有任何可能性,一個函數可能需要使用邏輯常量,那麼不要將它們標記爲按位常量!

+0

類似於你的'equal()',我已經完成了大部分函數參數'const',到目前爲止我還沒有遇到任何問題。這是因爲'const'還是壞了? – Arlen 2012-01-01 04:25:13

+0

我認爲const現在大部分都在工作。雖然(我認爲)Phobos中的一些東西並不是常量正確的,並且後期blit構造函數存在一個大問題,但我認爲大多數const正在工作。 – 2012-01-01 12:49:34

+0

因此,在添加const(在C++中)時,而不是具有更大的自由度,而不是相反;將參數設置爲const更具限制性? – 2012-01-04 00:25:39

6

D的immutable是可傳遞的,當給定一個不可變的引用(例如不可變成員函數中的this引用)時,所有字段也是不可變的。在D中沒有辦法解決這個問題。const只存在於D中綁定可變數據和不可變數據,但由於immutable隱式地轉換爲const,它也必須是可傳遞的。一旦你變得不可變(或者const),你就不能回去了。

好處有幾個:不可變的數據可以安全地跨線程共享,如果需要可以放在ROM中,並且很容易推理。在D中根本沒有邏輯常量的空間,不論好壞。

+0

所以你建議我做'_c1','_c2','計算( )'和'A'的所有引用都是非const的? – Arlen 2011-12-30 05:48:55

+0

@Arlen,如果你需要改變方法中的this對象,這是你唯一的選擇。請注意,您仍然可以改變其他地方存儲的數據(duh),當您的目的是將可變數據用於緩存目的時,您有時可以使用這些數據。但是這種外部緩存在一般情況下是醜陋的(哈希映射等到伴隨的緩存?Ew!)並且仍然是一個未解決的問題。 – 2011-12-30 06:02:21

4

短版;你不能,通過設計。

D的設計者在更長的版本中得出結論(在一些史詩般的辯論之後)認爲可變的好處超過了缺點。 (參見:jA_cOp的答案的一些細節,許多其他reaons的由意向驅動,使並行編程和推理有少醜陋的。)