Note that there are some explanatory texts on larger screens.

plurals
  1. POWhat is the best strategy to store objects ensuring unique name and being able to efficiently retrieve them later, in c++?
    primarykey
    data
    text
    <p>I'm coding a Composite class (similar to <code>QObject</code> of Qt) and at the moment I'm storing the children in a <code>std::vector</code>. Each Composite instance has a name and this name has to be unique between all the other instances that are siblings of this one, or probably better said, between the instances that share the same parent.</p> <p>Each time a new instance is pushed inside the <code>vector</code>, I must look if its name is already used by one of the instances already in the <code>vector</code>, if it does, I must change its name adding a number.</p> <p>The code I came up with is quite silly and very slow when the number of children become consistent.</p> <p>here is the class:</p> <pre><code>class Composite { public: Composite(const std::string &amp;name, Composite *ancestor=NULL); ~Composite(); private: std::string name; Composite *ancestor; std::vector&lt;Composite*&gt; descendants; public: void setName(const std::string &amp;name); }; </code></pre> <p>this is the constructor and <code>setName</code> implementation:</p> <pre><code>Composite::Composite(const std::string &amp;name, Composite *ancestor) { this-&gt;ancestor = ancestor; setName(name); if (ancestor!=NULL) ancestor-&gt;descendants.push_back(this); } </code></pre> <p>.</p> <pre><code>void Composite::setName(const std::string &amp;name) { this-&gt;name = name; if (ancestor!=NULL) { CompositeList::iterator dIt; for( dIt=ancestor-&gt;descendants.begin(); dIt!=ancestor-&gt;descendants.end(); dIt++) { if ((*dIt)==this) { continue; } else if (this-&gt;name == (*dIt)-&gt;getName()) { int trailingNumber = stringToInt(getTrailingNumber(this-&gt;name)); std::string cleanName = removeTrailingNumber(this-&gt;name); this-&gt;name = cleanName+intToString(trailingNumber+1); } } } } </code></pre> <p>This might be fine for very few children, but when they become hundreds then the <code>setName</code> function really become slow. Imagine this situation:</p> <pre><code>Composite *parent = new Composite("pippo"); for (int i=0; i&lt;10000; i++) { Composite("ClashingName", parent); } </code></pre> <p>the first time is fine, the second time the name is changed in ClashingName0, the third time the name is firstly cahnged into ClashingName0, than it find the clashing with the second instance and set the name to ClashingName1... you got the idea, it is exponential, when it comes at the end of that loop an unacceptable amount of time is passed by.</p> <p>So the real problem here is how to efficiently find the name clashing and efficiently assign a new name that is not already used? Any std container is fine for me and my compiler support C++11, but I can't/want to use Boost because the project I'm working on is incredibly small (it is basically this class)</p> <p>I'm not exactly a seasoned user of C++, I was thinking to use <code>map</code> or <code>unordered_map</code> but I'm really hungry for experts' suggestions here. </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload