std::maps within std::maps -- optimisation

Discussion in 'C++' started by Simon Elliott, Mar 9, 2005.

  1. Here's a small example which uses std::maps within std::maps. Note the
    line flagged // *** copy?

    #include <iostream>
    #include <map>
    #include <string>

    struct Tfoo
    {
    Tfoo():i1_(0),i2_(0){}
    Tfoo(int i1, int i2):i1_(i1),i2_(i2){}
    int i1_;
    int i2_;
    };

    typedef std::map<std::string, Tfoo> TfooMapInner;
    typedef std::map<std::string, TfooMapInner> TfooMapOuter;

    int main(int argc, char **argv)
    {
    TfooMapOuter myFooMapOuter;

    {
    TfooMapInner myFooMapInner;
    myFooMapInner["inner_key_1"] = Tfoo(0,1);
    myFooMapInner["inner_key_2"] = Tfoo(0,2);
    myFooMapOuter["outer_key_1"] = myFooMapInner;
    }

    {
    TfooMapInner myFooMapInner;
    myFooMapInner["inner_key_3"] = Tfoo(0,3);
    myFooMapInner["inner_key_4"] = Tfoo(0,4);
    myFooMapOuter["outer_key_2"] = myFooMapInner;
    }

    TfooMapOuter::const_iterator ipOuter;
    TfooMapOuter::const_iterator epOuter = myFooMapOuter.end();
    for (ipOuter=myFooMapOuter.begin(); ipOuter!=epOuter; ++ipOuter)
    {
    const std::string& outerKey = (*ipOuter).first;
    const TfooMapInner& fooMapInner = (*ipOuter).second; // *** copy?
    TfooMapInner::const_iterator ipInner;
    TfooMapInner::const_iterator epInner = fooMapInner.end();
    for (ipInner=fooMapInner.begin(); ipInner!=epInner; ++ipInner)
    {
    const std::string& innerKey = (*ipInner).first;
    const Tfoo& foo = (*ipInner).second;
    cout << outerKey << " " << innerKey << " " << foo.i1_ << " "
    << foo.i2_ << std::endl;
    }
    }

    return 0;
    }

    This produces the output I expected:

    outer_key_1 inner_key_1 0 1
    outer_key_1 inner_key_2 0 2
    outer_key_2 inner_key_3 0 3
    outer_key_2 inner_key_4 0 4

    But I'm concerned about the line I flagged (// *** copy?)
    const TfooMapInner& fooMapInner = (*ipOuter).second;

    Is (*ipOuter).second a copy of the TfooMapInner? If so, how can I avoid
    this unnecessary copy being made?


    --
    Simon Elliott http://www.ctsn.co.uk
    Simon Elliott, Mar 9, 2005
    #1
    1. Advertising

  2. Simon Elliott

    Rolf Magnus Guest

    "Simon Elliott" <Simon at ctsn.co.uk> wrote:

    > Here's a small example which uses std::maps within std::maps. Note the
    > line flagged // *** copy?
    >
    > #include <iostream>
    > #include <map>
    > #include <string>
    >
    > struct Tfoo
    > {
    > Tfoo():i1_(0),i2_(0){}
    > Tfoo(int i1, int i2):i1_(i1),i2_(i2){}
    > int i1_;
    > int i2_;
    > };
    >
    > typedef std::map<std::string, Tfoo> TfooMapInner;
    > typedef std::map<std::string, TfooMapInner> TfooMapOuter;
    >
    > int main(int argc, char **argv)
    > {
    > TfooMapOuter myFooMapOuter;
    >
    > {
    > TfooMapInner myFooMapInner;
    > myFooMapInner["inner_key_1"] = Tfoo(0,1);
    > myFooMapInner["inner_key_2"] = Tfoo(0,2);
    > myFooMapOuter["outer_key_1"] = myFooMapInner;
    > }
    >
    > {
    > TfooMapInner myFooMapInner;
    > myFooMapInner["inner_key_3"] = Tfoo(0,3);
    > myFooMapInner["inner_key_4"] = Tfoo(0,4);
    > myFooMapOuter["outer_key_2"] = myFooMapInner;
    > }
    >
    > TfooMapOuter::const_iterator ipOuter;
    > TfooMapOuter::const_iterator epOuter = myFooMapOuter.end();
    > for (ipOuter=myFooMapOuter.begin(); ipOuter!=epOuter; ++ipOuter)
    > {
    > const std::string& outerKey = (*ipOuter).first;
    > const TfooMapInner& fooMapInner = (*ipOuter).second; // *** copy?
    > TfooMapInner::const_iterator ipInner;
    > TfooMapInner::const_iterator epInner = fooMapInner.end();
    > for (ipInner=fooMapInner.begin(); ipInner!=epInner; ++ipInner)
    > {
    > const std::string& innerKey = (*ipInner).first;
    > const Tfoo& foo = (*ipInner).second;
    > cout << outerKey << " " << innerKey << " " << foo.i1_ << " "
    > << foo.i2_ << std::endl;
    > }
    > }
    >
    > return 0;
    > }
    >
    > This produces the output I expected:
    >
    > outer_key_1 inner_key_1 0 1
    > outer_key_1 inner_key_2 0 2
    > outer_key_2 inner_key_3 0 3
    > outer_key_2 inner_key_4 0 4
    >
    > But I'm concerned about the line I flagged (// *** copy?)
    > const TfooMapInner& fooMapInner = (*ipOuter).second;
    >
    > Is (*ipOuter).second a copy of the TfooMapInner? If so, how can I avoid
    > this unnecessary copy being made?


    First insert the map, then fill it instead of the other way round:

    TfooMapInner& myFooMapInner = myFooMapOuter["outer_key_2"];
    myFooMapInner["inner_key_3"] = Tfoo(0,3);
    myFooMapInner["inner_key_4"] = Tfoo(0,4);
    Rolf Magnus, Mar 9, 2005
    #2
    1. Advertising

  3. Simon Elliott

    simont Guest

    Dereferencing (*ipOuter).second gives you a reference to the inner map
    instance which already exists in the outer map. Initialising a
    reference from that (as you do) just gives it a name.

    The only place a map is copied is when you're setting up (see Rolf's
    suggestion for avoiding that). You aren't copying anything in the bit
    you flagged.
    simont, Mar 9, 2005
    #3
  4. On 09/03/2005, Rolf Magnus wrote:
    > > Is (*ipOuter).second a copy of the TfooMapInner? If so, how can I
    > > avoid this unnecessary copy being made?

    >
    > First insert the map, then fill it instead of the other way round:
    >
    > TfooMapInner& myFooMapInner = myFooMapOuter["outer_key_2"];
    > myFooMapInner["inner_key_3"] = Tfoo(0,3);
    > myFooMapInner["inner_key_4"] = Tfoo(0,4);


    Thanks - that makes sense.

    --
    Simon Elliott http://www.ctsn.co.uk
    Simon Elliott, Mar 10, 2005
    #4
  5. On 09/03/2005, simont wrote:

    > Dereferencing (*ipOuter).second gives you a reference to the inner map
    > instance which already exists in the outer map. Initialising a
    > reference from that (as you do) just gives it a name.


    I take your point about the reference, but I was concerned that a
    std::pair might be created on the fly by the iterator. But now I come
    to think about it, this wouldn't be much use if you wanted to use the
    iterator to change the map data!

    > The only place a map is copied is when you're setting up (see Rolf's
    > suggestion for avoiding that). You aren't copying anything in the bit
    > you flagged.


    That's useful to know.

    --
    Simon Elliott http://www.ctsn.co.uk
    Simon Elliott, Mar 10, 2005
    #5
    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. Fredrik Ramsberg

    Optimisation of regexps in Perl?

    Fredrik Ramsberg, Oct 14, 2003, in forum: Perl
    Replies:
    2
    Views:
    471
    Fredrik Ramsberg
    Oct 15, 2003
  2. Roedy Green

    boolean loop optimisation

    Roedy Green, Sep 11, 2003, in forum: Java
    Replies:
    8
    Views:
    2,825
    Chris Uppal
    Sep 12, 2003
  3. sorry.no.email@post_NG.com

    Search Engine Optimisation

    sorry.no.email@post_NG.com, May 8, 2006, in forum: HTML
    Replies:
    0
    Views:
    348
    sorry.no.email@post_NG.com
    May 8, 2006
  4. Oliver Batchelor
    Replies:
    1
    Views:
    368
    Frank Schmitt
    Jul 22, 2003
  5. Marcus
    Replies:
    2
    Views:
    586
    Marcus
    Dec 9, 2005
Loading...

Share This Page