2011-03-08 80 views
4

根據SGI's doc on associative containers,「由於元素是根據它們的鍵來存儲的,所以與每個元素相關的鍵是不可變的是非常重要的」。我有時使用指針作爲std :: map的關鍵字,因爲儘管指向的對象可能是可變的,但指針本身是不變的。QPointer可以作爲std :: map的關鍵

QPointer在技術上是模仿指針的對象,Qt's doc表示我們可以像指針一樣使用QPointers。由於QPointer對象本身可能在執行過程中發生更改,它是否仍然可以用作std :: map容器的關鍵字?

編輯1:我不能使用QMap,我必須堅持std :: map。
編輯2:代碼編譯當我使用QPointer。問題在於我是否應該在運行時期待不愉快的意外。

+0

相關:?允許在有序的STL容器鍵指針(http://stackoverflow.com/questions/4913161/) – 2011-03-08 21:37:49

回答

6

不,這是不安全的,因爲當銷燬QObject時,QPointer<T>可能會更改爲NULL。 (QPointer類似於std::weak_ptr)。所以這個代碼將產生不確定的行爲:

class CopyableWidget : public QWidget { 
    Q_OBJECT; 
public: 
    CopyableWidget(Widget* parent = 0) : QWidget(parent) {} 
    CopyableWidget(const CopyableWidget& w, Widget* parent = 0) : QWidget(parent) {} 
}; 

std::vector<CopyableWidget> v(2); // Two default-constructed widgets 
std::map<QPointer<CopyableWidget>, int> wid_values; 
wid_values[&v[0]] = 1; 
wid_values[&v[1]] = 2; 
// wid_values contains { {&v[0], 1}, {&v[1], 2} } 
v.resize(1); 
// The QPointer in wid_values constructed from &v[1] now acts like NULL. 
// wid_values contains { {&v[0], 1}, {NULL, 2} } 
// But &v[0] > NULL (on most platforms). Class invariant was violated! 
0

我認爲如果你不重新指定它並且不刪除底層對象,那麼QPointer不會「神奇地」改變它指向的位置,所以它應該是安全的。

(我必須補充一點,我見過的Qt違反了最小驚訝多次的原則,所以測試是肯定的。)

+1

Qt是開源的。不要測試,只需看代碼即可。 – BatchyX 2011-03-08 21:47:24

0

這是不確定的行爲比較來自不同的分配塊的指針比平等的其他任何/不等式。即用new或malloc分配一個塊後,可以遍歷緩衝區並測試指針是否小於緩衝區的末尾。但是你不能做兩個單獨的新聞/ malloc並比較除了平等/不平等以外的任何結果的指針。

呃...你可以但你可能不喜歡結果。

+1

但關聯容器使用'std :: less',它被定義爲適用於任何指針類型。 – 2011-03-08 21:47:21

+0

也許我正在使用的文檔已過時。我正在看標準的一部分,它指出指針之間的關係運算符給出未指定的行爲,除非它們指向相同的分配。這不再是真的嗎? – Brad 2011-03-08 21:57:41

+2

關聯容器不使用關係運算符,它們使用'std :: less'。即使關係運算符不這樣做,也可以明確定義指針的總排序。 – 2011-03-08 22:02:10

相關問題