<div dir="ltr">Yep, as Krzysztof mentioned - pointer invalidation when inserting elements into a SmallVector (std::vector has similar guarantees here). Adding new elements can require a reallocation - moving all the objects over into the new allocation, so any pointers pointing to the original elements would be invalid. (though, yeah, before you get to that point - you already have dangling references because you're pointing to the RV temporary, uinstead of the copy of RV in the vector)<br><br>You could use indexes as Krzysztof mentioned - other options include using non-invalidating data structures (like std::list or std::deque) or indirection (a SmallVector of unique_ptr<RecordVal> - so that pointers remain stable/valid) (though both those solutions involve extra memory/allocation overhead) or putting the RV in the map and pointing to it from the vector (unordered_map has pointer stability through insertion and removal - though llvm's DenseMap does not have such a guarantee). Or maybe llvm's MapVector would abstract you from the complexities of all these options?</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, Nov 30, 2020 at 12:20 PM Paul C. Anagnostopoulos via llvm-dev <<a href="mailto:llvm-dev@lists.llvm.org">llvm-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Okay, I'm at a loss to understand what I'm doing wrong with the unordered_map class. Thank you for any help you can give.<br>
<br>
I have two data structures:<br>
<br>
  SmallVector<RecordVal, 0> Values;<br>
  std::unordered_map<const Init *, const RecordVal *> ValueMap; <br>
<br>
I just added the unordered_map to experiment with faster lookups for the fields in  TableGen records. The key is a StringInit and the corresponding value is a RecordVal. I made it a pointer to the RecordVal since the existing SmallVector holds the actual RecordVal instance.<br>
<br>
Here is the code that adds a field to the structures:<br>
<br>
  void addValue(const RecordVal &RV) {<br>
    Values.push_back(RV);<br>
    ValueMap[RV.getNameInit()] = &RV; <br>
<br>
The RecordVal is push_backed onto the vector and inserted into the map by assignment.<br>
<br>
Here is the code that looks up an entry. First the new code and then the old code.<br>
<br>
  const RecordVal *getValue(const Init *Name) const {<br>
    auto It = ValueMap.find(Name);<br>
    if (It != ValueMap.end()) {<br>
      return It->second;<br>
    }<br>
    return nullptr;<br>
<br>
    for (const RecordVal &Val : Values)<br>
      if (Val.Name == Name) {<br>
        return &Val;<br>
      }<br>
    return nullptr;<br>
  }<br>
<br>
As far as I can tell, 'return It->second' is not returning the RecordVal. However, I'm thoroughly confused because I threw in a ton of prints to check it. Using It->Second I can print the name and value of the RecordVal and they are correct. I even printed the addresses of the name and value data structures from both It-Second and Val and they are the same. But when I print the address It-Second and  the address &Val, they are different. <br>
<br>
(Indeed, I should use Visual Studio to look at this, but that is a lesson for another day.)<br>
<br>
_______________________________________________<br>
LLVM Developers mailing list<br>
<a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
</blockquote></div>