1

I have QMap that stores objects and I want to store pointers to these objects for some external processing. Will the pointer to the object remain valid after inserting/deleting some values from map? To illustrate:

QMap <QString, QString> map;

map.insert("one", "one");
map.insert("two", "two");
map.insert("three", "three");

QString *pointer = &map["one"];
qDebug()<<*pointer;

map.insert("aaa", "aaa");
map.insert("bbb", "bbb");
qDebug()<<*pointer;

map.insert("zzz", "zzz");
map.insert("xxx", "xxx");
qDebug()<<*pointer;

Is it guaranteed that pointer will point to the exact same object after any number of insertions/deletions (considering of course that this object was not removed)

Or should I consider storing pointers instead of objects?

Bearded Beaver
  • 646
  • 4
  • 21
  • Values in the map are stored by value even if in these case it means that the pointer (address which it points) is stored by value [For example](https://stackoverflow.com/questions/14340672/invalidate-pointer-values-inside-a-qmap) – Vahagn Avagyan Jul 18 '17 at 19:18
  • Have you considered using `std::map` instead? Standard containers' invalidation rules are thoroughly documented and more generally understand. – François Andrieux Jul 18 '17 at 19:34
  • [This link](http://doc.qt.io/qt-5/qmap-iterator.html#details) indicates that insertion in a `QMap` does not invalidate iterators. *"If you add items to the map, existing iterators will remain valid."* It's likely that pointers to existing elements are also preserved but it's not explicitly stated. – François Andrieux Jul 18 '17 at 19:36

1 Answers1

1

Doing a minor modification to your code:

  QMap <QString, QString> map;

  map.insert("one", "one");
  map.insert("two", "two");
  map.insert("three", "three");

  QString *pointer = &map["one"];
  qDebug()<<pointer;

  map.insert("aaa", "aaa");
  map.insert("bbb", "bbb");
  pointer = &map["one"];
  qDebug()<<pointer;

  map.insert("zzz", "zzz");
  map.insert("xxx", "xxx");
  pointer = &map["one"];
  qDebug()<<pointer;

reveals that it looks like it remains valid.

QMap elements are sorted as they are inserted. The underlying data structure is a red-black tree (in Qt5 at least, IIRC it was a skip list in Qt4). Nodes are evidently stored on the heap rather than pools, as it doesn't come with a reserve(space) method, which would only be applicable if it used pools.

There is no good reason for a tree node to be reallocated to another memory location, as the tree structure is easily redefined by changing leaf pointer values.

So yeah, pointers should persist as the map changes, as long as that particular key entry is not removed.

dtech
  • 47,916
  • 17
  • 112
  • 190
  • Bear in mind the whole "deferred detach" magic in Qt which can result in re-allocation (as the next write-access triggers copy, even if you only handed out a read-only copy). Even though the structure itself doesn't move/copy during single-instance operation, it does so after being copied, and it does so in the source! – Ext3h Dec 24 '20 at 13:59