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 unpleasant 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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With