reassign keys in an STL map

Discussion in 'C++' started by Shailesh Humbad, Oct 29, 2004.

  1. 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);
    }
     
    Shailesh Humbad, Oct 29, 2004
    #1
    1. Advertising

  2. Shailesh Humbad wrote:
    > 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<int, MyObject*> Box;

    >
    > [...]
     
    Victor Bazarov, Oct 29, 2004
    #2
    1. Advertising

  3. Victor Bazarov wrote:
    > Store pointers to objects.
    >
    >>
    >> map<int, MyObject> Box;

    >
    >
    > 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);
    }
     
    Shailesh Humbad, Oct 29, 2004
    #3
  4. Shailesh Humbad wrote:
    > Victor Bazarov wrote:
    >
    >> Store pointers to objects.
    >>
    >>>
    >>> map<int, MyObject> Box;

    >>
    >>
    >>
    >> 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?


    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
     
    Victor Bazarov, Oct 29, 2004
    #4
  5. Shailesh Humbad

    Greg Schmidt Guest

    On Fri, 29 Oct 2004 21:47:52 GMT, Shailesh Humbad wrote:

    > Victor Bazarov wrote:
    >> Store pointers to objects.
    >>
    >>>
    >>> map<int, MyObject> Box;

    >>
    >> 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);
    > }


    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.

    --
    Greg Schmidt
    Trawna Publications http://www.trawna.com/
     
    Greg Schmidt, Oct 29, 2004
    #5
  6. Victor Bazarov wrote:
    > Shailesh Humbad wrote:
    >
    >> Victor Bazarov wrote:
    >>
    >>> Store pointers to objects.
    >>>
    >>>>
    >>>> map<int, MyObject> Box;
    >>>
    >>>
    >>>
    >>>
    >>> 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?

    >
    >
    > 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.
     
    Shailesh Humbad, Oct 30, 2004
    #6
  7. >
    > 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
     
    John Harrison, Oct 30, 2004
    #7
  8. Shailesh Humbad

    Greg Schmidt Guest

    On Sat, 30 Oct 2004 07:33:45 +0100, John Harrison wrote:

    >>
    >> 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.


    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.

    --
    Greg Schmidt
    Trawna Publications http://www.trawna.com/
     
    Greg Schmidt, Nov 2, 2004
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. =?Utf-8?B?VGltOjouLg==?=

    Reassign value to private

    =?Utf-8?B?VGltOjouLg==?=, Jan 27, 2005, in forum: ASP .Net
    Replies:
    2
    Views:
    383
    =?Utf-8?B?VGltOjouLg==?=
    Jan 27, 2005
  2. biswaranjan.rath

    how to reassign variable

    biswaranjan.rath, May 5, 2006, in forum: XML
    Replies:
    3
    Views:
    7,828
    biswaranjan.rath
    May 5, 2006
  3. alan
    Replies:
    3
    Views:
    380
    Victor Bazarov
    Nov 28, 2007
  4. Bernhard Merkle

    reassign to builtin possible !?

    Bernhard Merkle, Jan 3, 2008, in forum: Python
    Replies:
    8
    Views:
    309
    Bernhard Merkle
    Jan 4, 2008
  5. Immortal Nephi

    Reassign two objects to one pointer?

    Immortal Nephi, May 19, 2009, in forum: C++
    Replies:
    1
    Views:
    322
    Bart van Ingen Schenau
    May 20, 2009
Loading...

Share This Page