reassign keys in an STL map

S

Shailesh Humbad

I have a class and map like this:

class MyObject {
...
};

map<int, MyObject> Box;

Now, I want to reassign the keys of one or more of the pairs in Box
based on another map<int, int> that stores the key assignment like
(old, new). Since MyObject may be big, this should be done without
invoking the MyObject copy constructor. For example, if the map was
like (1 => a, 2 => b, 3 => c), then it might change to (3 => a, 1 =>
b, 2 => c). I figured out how to do the reassignment with STL, but
I'm not sure how to prevent the copying. Any suggestions?

map<int, MyObject> Box;

void
ReassignKeys(std::map<int, int>& ReassignmentMap)
{
map<int, MyObject> tempBox;
map<int, int>::iterator ReassignmentIterator;
map<int, MyObject>::iterator ObjectsIterator;

// Do nothing if nothing to reassign.
if(ReassignmentMap.size() == 0)
{
return;
}

// Loop through each reassignment and add the object to the new
for(ReassignmentIterator = ReassignmentMap.begin();
ReassignmentIterator != ReassignmentMap.end();
ReassignmentIterator++)
{
// First make sure the old key exists
assert(Box.end() !=
Box.find(ReassignmentIterator->first));

// Now get the object based on the old key, and add it to the
// temporary container with the new key
tempBox.insert(map<int, MyObject>::value_type(
ReassignmentIterator->second, // new key
Box[ReassignmentIterator->first]) ); // find object by old

// Remove the object from the original container
Box.erase(ReassignmentIterator->first);
}

// Add any objects that weren't reassigned to the new container
for(ObjectsIterator = Box.begin();
ObjectsIterator != Box.end(); ObjectsIterator++)
{
// Make sure the key doesn't already exist in the new map
assert(tempBox.end() == tempBox.find(ObjectsIterator->first));

// Insert the pair into the new map
tempBox.insert(map<int, MyObject>::value_type(
ObjectsIterator->first, ObjectsIterator->second));
}

// Erase the old map
Box.clear();

// Now swap the old with the new
Box.swap(tempBox);
}
 
V

Victor Bazarov

Shailesh said:
I have a class and map like this:

class MyObject {
...
};

map<int, MyObject> Box;

Now, I want to reassign the keys of one or more of the pairs in Box
based on another map<int, int> that stores the key assignment like (old,
new). Since MyObject may be big, this should be done without invoking
the MyObject copy constructor. For example, if the map was like (1 =>
a, 2 => b, 3 => c), then it might change to (3 => a, 1 => b, 2 => c). I
figured out how to do the reassignment with STL, but I'm not sure how to
prevent the copying. Any suggestions?

Store pointers to objects.
map<int, MyObject> Box;

map said:
 
S

Shailesh Humbad

Victor said:
Store pointers to objects.



map<int, MyObject*> Box;

There's no other way? I want to use as much automatic memory
management as possible. Specifically, is there a way to extract a
group containing objects from a map without copy construction?

Maybe I'm understanding this wrong.

Suppose I do this:

void InsertObject() {
map<int, MyObject*> Box;
MyObject newObject;

Box.insert(map<int, MyObject*>::value_type(1, &newObject);
}

Now, I have stored the pointer to the local variable. I'm assuming
once the function returns, the object will be destroyed even though we
have a pointer to it saved in the box. That means I have to do this:

void InsertObject() {
map<int, MyObject*> Box;
MyObject * newObject;

newObject = new MyObject();

Box.insert(map<int, MyObject*>::value_type(1, newObject);
}
 
V

Victor Bazarov

Shailesh said:
There's no other way? I want to use as much automatic memory management
as possible. Specifically, is there a way to extract a group containing
objects from a map without copy construction?

What do you mean by "extract"?
Maybe I'm understanding this wrong.

Suppose I do this:

void InsertObject() {
map<int, MyObject*> Box;
MyObject newObject;

Box.insert(map<int, MyObject*>::value_type(1, &newObject);

Parentheses are mismatched. I take it you meant

Box[1] = &newObject;
}

Now, I have stored the pointer to the local variable.

And you stored it in a local object too.
I'm assuming once
the function returns, the object will be destroyed even though we have a
pointer to it saved in the box.

And the container is going to be destroyed as well.
That means I have to do this:

void InsertObject() {
map<int, MyObject*> Box;
MyObject * newObject;

newObject = new MyObject();

Box.insert(map<int, MyObject*>::value_type(1, newObject);

Box[1] = newObject;

Why? You don't seem to be using Box anywhere outside the function,
so the first approach should be just fine.

Yes, if you want 'Box' to live outside the 'InsertObject' function,
you need to make sure the pointer is valid outside that function.

Pointers are higher maintenance, no doubt. But they present MUCH less
copying. So, it's up to you. There is no free cheese.

V
 
G

Greg Schmidt

There's no other way? I want to use as much automatic memory
management as possible. Specifically, is there a way to extract a
group containing objects from a map without copy construction?

Maybe I'm understanding this wrong.

Suppose I do this:

void InsertObject() {
map<int, MyObject*> Box;
MyObject newObject;

Box.insert(map<int, MyObject*>::value_type(1, &newObject);
}

Now, I have stored the pointer to the local variable. I'm assuming
once the function returns, the object will be destroyed even though we
have a pointer to it saved in the box. That means I have to do this:

void InsertObject() {
map<int, MyObject*> Box;
MyObject * newObject;

newObject = new MyObject();

Box.insert(map<int, MyObject*>::value_type(1, newObject);
}

That's right. To get back towards your goal of automatic memory
management, you could use a shared pointer such as Boost's shared_ptr, like
this (untested):

typedef boost::shared_ptr<MyObject> MyObjectPtr_t;
void InsertObject() {
map<int, MyObjectPtr_t> Box;
MyObjectPtr_t newObject;

newObject = MyObjectPtr_t (new MyObject());

Box.insert(map<int, MyObjectPtr_t>::value_type(1, newObject);
// or Box[1] = newObject;
}

Note that std::auto_ptr is explicitly not acceptable for this use.
 
S

Shailesh Humbad

Victor said:
What do you mean by "extract"?

Extract means get a pointer to the object.
Box.insert(map<int, MyObject*>::value_type(1, newObject));
Box[1] = newObject;

That's a useful syntax that I didn't know about before. Thanks for
pointing it out.
Why? You don't seem to be using Box anywhere outside the function,
so the first approach should be just fine.

Yes, if you want 'Box' to live outside the 'InsertObject' function,
you need to make sure the pointer is valid outside that function.

Pointers are higher maintenance, no doubt. But they present MUCH less
copying. So, it's up to you. There is no free cheese.

V

The example is contrived, but yes, Box is used outside the function.
I guess I will just go with pointers, because copying will be
unacceptable performance-wise, and I don't have time for boost right now.

Thanks for your input.
 
J

John Harrison

The example is contrived, but yes, Box is used outside the function. I
guess I will just go with pointers, because copying will be unacceptable
performance-wise, and I don't have time for boost right now.

Boost is easy, takes about ten minutes to setup, works like a charm.

john
 
G

Greg Schmidt

Boost is easy, takes about ten minutes to setup, works like a charm.

Particularly since the part you'd need (shared_ptr) is not in one of the
libraries that needs to be built. It's all in the headers, so just
download, unzip, and point your compiler at the include directory. The
time you'll spend doing this, plus reading the documentation of the
required class and learning how to use it, will be saved right away when
you don't have to bother figuring out when and how to delete everything
you've new'ed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

Sorting an STL map 1
swapping keys 5
stl::map iterator 2
STL::MAP: Printing values only once .. 9
Modify STL map Object 4
STL Map Problem 3
STL map insert Options 8
STL map and char * problems 3

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,682
Members
48,796
Latest member
Greg L.

Latest Threads

Top