2017-08-08 39 views
0

我有一個MyList的QList。從列表中追加和刪除項目很少見,並且受共同列表互斥體控制。 MyClass的包含幾個子和個人QReadWriteLock:QReadWriteLock在訪問器

MyClass{ 
private: 
    Substructure substructure; 
    QReadWriteLock rwlElem; 
} 

我把儲物櫃accesors這樣的:

Substructure MyClass::getSub(){ 
    QReadLocker lock(&rwlElem); 
    return substructure; 
} 

我希望下部結構的副本將安全返回。我在二傳手中做出的同樣的事情。這種使用儲物櫃的好習慣?首先會發生什麼情況:複製底層結構或毀壞儲物櫃?

回答

0

我會回答你的最後一個問題開始:

什麼第一發生:更衣室的子或破壞的拷貝構造?

TL; DR:複製構造發生在銷燬所有局部變量之前。

這已經在stackoverflow上多次詢問過,請參閱here,herehere

更精確的措詞已經由CWG 1885施加到C++ 14標準:

N4606§6.6.3[stmt.return]/3

的結果的副本初始化在返回語句的操作數所建立的完整表達式結尾的臨時對象被破壞之前,該調用被依次排序,而在銷燬封閉返回的塊的局部變量(6.6)之前被排序聲明。


我有MyClass的的的QList。從列表中追加和刪除項目很少見,並且受共同列表互斥體控制。 MyClass的包含幾個子和個人QReadWriteLock

有兩個互斥鎖可以讓你容易死鎖。然而,你能避免通過下面的這兩個準則之一:

  • 避免嵌套鎖,一次只鎖定一個互斥體。確保在獲得新鎖之前釋放您當前持有的鎖。
  • 如果這對你來說是不可能的,你必須總是以固定順序獲得你的鎖,而且這個順序應該在整個應用程序中保持一致(即在鎖定一個特定的鎖之前總是鎖住保護整個列表的鎖MyClass當您需要同時鎖定兩個互斥鎖時,實例的讀/寫互斥鎖)。

同樣的事情,我在做setter方法。這種使用儲物櫃的好習慣?

假設您在您的設置器中使用了QWriteLocker,這應該沒問題(從不會導致未定義的行爲的意義上說)。但是你必須注意你的界面真正在說什麼。例如,當你正在做這樣的事情,以一個實例MyClass類型的mc

Substructure s = mc.getSub(); 
if(s == anotherSubstructure) 
    mc.doSomething(); 

通過執行上面的代碼中的線程獲取與anotherSubstructure比較s的時候,另一個線程可能會改變內部mc實際substructure,並且此更改對前一個線程不可見(因爲它獲得了substructure的自己的副本)。

的一點是,當你做Substructure s = mc.getSub();,你要知道的唯一的事情是,mc的子等於s在某個時間點,併爲您解除鎖定該值可能儘快改變在你的getSub函數中。

在我上面的例子中,doSomething()不能認爲mc的子結構的值仍然等於anotherSubstructure。您可能需要對需要在自己的函數中進行原子操作的操作進行分組(鎖確保在上述情況下值不會更改)。