Can QPointer be the key to std :: map

According to the SGI doc in associative containers : "Since the elements are stored according to their keys, it is important that the key associated with each element is immutable." I sometimes use the pointer as a key to std :: map, because although the specified object may be mutable, the pointer itself is constant.

QPointer is technically an object that mimics a pointer, and Qt doc says we can use QPointers just like pointers. Since the QPointer object itself can change at run time, can it still be used as the key to the std :: map container?

Edit 1: I cannot use QMap, I have to stick to std :: map.
Editing 2: The code compiles when I use QPointer. The question is whether to expect unpleasant surprises at runtime.

+4
source share
3 answers

No, this is not safe, because QPointer<T> can change to NULL when QObject is destroyed. ( QPointer is similar to std::weak_ptr .) Thus, this code would create Undefined Behavior:

 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! 
+6
source

I take (by principle of least surprise) that QPointer will not “magically” change where it indicates, unless you reassign it and delete the underlying object, so it should be safe.

(I should add that I have seen Qt violate the principle of least surprise several times, so check to make sure.)

0
source

This behavior is undefined to compare pointers with different distribution blocks for anything other than equality / inequality. That is, after allocating a block using new or malloc, you can go through the buffer and test if your pointer is less than the end of the buffer. But you cannot do two separate news / mallocs and compare the resulting pointers for anything other than equality / inequality.

Well ... you can, but you may not like the results.

0
source

Source: https://habr.com/ru/post/1342897/


All Articles