Can a QPointer be the key to a std::map
According to SGI's doc on associative containers, "Since elements are stored according to their keys, it is essential that the key associated with each element is immutable". I sometimes use a pointer as a key to std::map, since, although the pointed object might be mutable, the pointer itself is constant.
QPointer is technically an object mimicking a pointer, and Qt's doc says that we can use QPointers exactly like pointers. Since the QPointer object itself may change during execution, can it still be used as the key to a std::map container?
Edit 1 : I can't use a QMap, I have to stick to std::map.
Edit 2 : The code compiles when I use a QPointer. The question is about whether I should expect unpl开发者_开发技巧easant surprises at runtime.No, this is not safe, because QPointer<T>
may change to NULL
when a QObject
is destroyed. (QPointer
is similar to std::weak_ptr
.) So this code would produce 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!
I take it (from the principle of least surprise) that a QPointer
won't "magically" change where it points if you don't reassign it and don't delete the underlying object, so it should be safe.
(I must add that I've seen Qt violate the principle of least surprise several times, so test to be sure.)
It is undefined behavior to compare pointers from different allocation blocks for anything other than equality/inequality. I.e. After allocating a block with new or malloc, you can walk through the buffer and test if your pointer is less than the end of the buffer. But you can't 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.
精彩评论