romeovs
romeovs

Reputation: 5953

C++ copy a vector structure, but with different objects

I've got a vector of std::string that represents the structure of another vector of object pointers. I would like to generate this vector of object pointers, where if there are two of the same objects, the pointer in the vector is also the same.

Don't know what I meant just there? let me give you an example. Let's say I have a std::vector of std::string:

std::vector<std::string> names;
names.push_back(std::string("A"));
names.push_back(std::string("A"));
names.push_back(std::string("B"));
names.push_back(std::string("C"));
names.push_back(std::string("A"));

Now let's say these names (A, B and C) represent three different instances of an Object:

Object* ptr_A = new Object(1); // A
Object* ptr_B = new Object(2); // B
Object* ptr_C = new Object(3); // C

I would now like to generate the vector that holds pointers to the Object, in the same order as in the vector names:

std::vector<Object*> objects;
objects.push_back(ptr_A);
objects.push_back(ptr_A);
objects.push_back(ptr_B);
objects.push_back(ptr_C);
objects.push_back(ptr_A);

so that when two names are the same, the pointers are the same also.

How would I efficiently do this? Note that I would like the objects to be dynamically allocated inside the function that does this, so that the vector can be used later on.

I will be using this to read the objects from a file based on a name, but I want to prevent making multiple objects that are basically the same.

Since this is homework I cannot use C++11 yet.

Upvotes: 0

Views: 212

Answers (2)

Mooing Duck
Mooing Duck

Reputation: 66971

This generates a lookup object that maps the names to allocated objects, and then fills the vector objects with the values based off the values in names. Simple.

typedef std::map<std::string, Object*>::iterator iterator;
typedef std::pair<std::string, Object*> value_type;
std::map<std::string, Object*> lookup;  //or maybe unordered_map
lookup.insert(value_type("A", ptr_A));
lookup.insert(value_type("B", ptr_B));
lookup.insert(value_type("C", ptr_C));

for(int i=0; i<names.size(); ++i) {
    iterator iter = lookup.find(names[i]);
    if (iter == lookup.end())
         throw std::runtime_error("invalid name in file");
    objects.push_back(iter->second);
}

If you want to generate the names and objects from the file, you can do something like this to create the names, objects, and the mapping between them all at once. I assume that you will have to do other stuff as well, I don't know your file format.

std::string newname;
std::map<std::string, Object*> lookup;  //or maybe unordered_map
while(myfile >> newname)
    lookup[newname] = new Object(newname);

Upvotes: 4

Casey
Casey

Reputation: 10966

Instead of using a std::vector, use a std::map containing keys of std::string and values of Object*

std::map<std::string, Object*>

No two identical keys may be inserted into the map. If an insert is attempted that matches a previous key the original key-value is returned. When a key is requested, the same pointer is returned.

Upvotes: 1

Related Questions