or is there any i am missing here which would be better?
Thanks in advance
There is no measurable difference between the two if the key is not
currently present in the map. If the key is already present in the map,
then the first statement overwrites the value associated with it,
whereas the second does nothing (but its return value lets you know
whether or not the insertion occurred).
--
With best wishes,
Igor Tandetnik
"On two occasions, I have been asked [by members of Parliament], 'Pray,
Mr. Babbage, if you put into the machine wrong figures, will the right
answers come out?' I am not able to rightly apprehend the kind of
confusion of ideas that could provoke such a question." -- Charles
Babbage
"Igor Tandetnik" <itand...@mvps.org> wrote in message
news:Oxr$eDUtE...@TK2MSFTNGP11.phx.gbl...
Theoritically I think the second way is faster, because in the first
case an element is constructed with the default constructor, then the
new value is copied in with operator =. I'm not sure if the compiler is
at liberty to optimize the first method and just call the copy constructor.
Jason
For the second method the value_type (std::pair<key,value>) is constructed
(in the call) and then copy-constructed if a node is inserted, so it's not
clear to me if there's any reason to belive that one will be consistently
faster than the other. If the value is a type that is expensive to create
and copy but inexpensive to default-construct, then it's likely that the
first method will be more efficient, seems to me.
-cd
... But note how in the example provided, an extra temporary copy of
both key and value are constructed as part of MAPTYPE::value_type, then
copy-constructed into the map's node. I'm not sue there's a way to call
map::insert() in a way that avoids these extra copies.
> I'm not sure if the compiler
> is at liberty to optimize the first method and just call the copy
> constructor.
I don't think so - not at the C++ semantic level. Of course if the
compiler can inline both the default constructor and the assignment
operator, and see that there are no side effects, it can blend the two
together, possibly optimizing large pieces away in the process.
We need rvalue references!
Tom
Here here!
-cd
> There is no measurable difference between the two if the key is not
> currently present in the map.
Yes there is. I went away and measured it with VC7.1.
See the bottom of
http://www.google.com/groups?hl=en&lr=&safe=off&selm=uD4yVyAeBHA.2284%40tkmsftngp05&rnum=9
But I decided that what I tested was not sufficiently comprehensive enough.
So doing (please view using "Courier New", a fixed-width font so everything
lines up)
(i) use map.insert(make_pair(key,value));
(ii) use map.insert(pair(key,value));
(iii) use map.insert(map::value_type(key,value));
(iv) use map.insert(p); where p is a pre-built pair
(v) use map[key] = value;
(vi) use map.insert(p); where p is a pre-built pair and there is
already a key in the map
(vii) use map[key] = value; where there is already a key in the map
I see operations
key value
ctor cctor dtor ctor cctor dtor assign op
(i) - 4 3 - 4 3 -
(ii) - 3 2 - 3 2 -
(iii) - 2 1 - 2 1 -
(iv) - 2 1 - 2 1 -
(v) - 2 1 1 2 2 1
(vi) - 1 1 - 1 1 -
(vii) - - - - - - 1
So there is no difference between inserting doing (iii) or (iv) but using
(v) there is extra constructor, assignment operator and destructor for the
value.
For the "successful insertion" cases (i) to (v), the total number of ctors -
dtors is always 1 as of course you wind up with a key,value pair in the map.
(iii) and (iv) are the most efficient (and best still with a good iterator
hint)
Here is test code
>>>>>>>>>>>>>>
#include <map>
#include <string>
#include <iomanip>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <utility>
using namespace std;
class Key
{
public:
Key(const char *sz) : sData(sz)
{
if (bVerbose) cout << "Key const C-string ctor\n";
}
Key(char *sz) : sData(sz)
{
if (bVerbose) cout << "Key C-string ctor\n";
}
Key(const string &s) : sData(s)
{
if (bVerbose) cout << "Key const string ctor\n";
}
Key()
{
if (bVerbose) cout << "Key dflt ctor\n";
}
~Key()
{
if (bVerbose) cout << "Key dtor\n";
}
Key(const Key &rhs) : sData(rhs.sData)
{
if (bVerbose) cout << "Key copy ctor\n";
}
Key &operator = (const Key &rhs)
{ sData = rhs.sData;
if (bVerbose) cout << "Key assignment\n";
return *this;
}
bool operator < (const Key &rhs) const
{
return (sData < rhs.sData);
}
static void VerboseOn() { bVerbose = true; }
static void VerboseOff() { bVerbose = false; }
private:
string sData;
static bool bVerbose;
};
class Value
{
public:
Value(const char *sz) : sData(sz)
{
if (bVerbose) cout << "Value const C-string ctor\n";
}
Value(char *sz) : sData(sz)
{
if (bVerbose) cout << "Value C-string ctor\n";
}
Value(const string &s) : sData(s)
{
if (bVerbose) cout << "Value const string ctor\n";
}
Value()
{
if (bVerbose) cout << "Value dflt ctor\n";
}
~Value()
{
if (bVerbose) cout << "Value dtor\n";
}
Value(const Value &rhs) : sData(rhs.sData)
{
if (bVerbose) cout << "Value copy ctor\n";
}
Value &operator = (const Value &rhs)
{ sData = rhs.sData;
if (bVerbose) cout << "Value assignment\n";
return *this;
}
static void VerboseOn() { bVerbose = true; }
static void VerboseOff() { bVerbose = false; }
private:
string sData;
static bool bVerbose;
};
bool Key::bVerbose;
bool Value::bVerbose;
static void VerboseOn()
{
Key::VerboseOn();
Value::VerboseOn();
}
static void VerboseOff()
{
Key::VerboseOff();
Value::VerboseOff();
}
int main(void)
{
VerboseOff();
map<Key, Value> m;
Key t1("a");
Key t2("b");
Key t3("c");
Value tv("d");
Value tv2("e");
pair<Key, Value> p(t3, tv);
//
// === make_pair test
//
VerboseOn();
cout << "make_pair test Start\n";
m.insert(make_pair(t1, tv));
cout << "make_pair test Stop\n\n";
VerboseOff();
m.clear();
//
// === pair test
//
VerboseOn();
cout << "pair test Start\n";
m.insert(pair<Key, Value>(t2, tv));
cout << "pair test Stop\n\n";
VerboseOff();
m.clear();
//
// === value_type test
//
VerboseOn();
cout << "value_type test Start\n";
m.insert(map<Key, Value>::value_type(t2, tv));
cout << "value_type test Stop\n\n";
VerboseOff();
m.clear();
//
// === pre-formed pair test
//
VerboseOn();
cout << "pre-formed pair test Start\n";
m.insert(p);
cout << "pre-formed pair test Stop\n\n";
VerboseOff();
m.clear();
//
// === [] test insert
//
VerboseOn();
cout << "[] test insert Start\n";
m[t2] = tv;
cout << "[] test insert Stop\n\n";
VerboseOff();
m.clear();
//
// === pre-formed pair test - insert failure
//
m.insert(p);
VerboseOn();
cout << "pre-formed pair failure test Start\n";
m.insert(p);
cout << "pre-formed pair failure test Stop\n\n";
VerboseOff();
m.clear();
//
// === [] test insert
//
m[t2] = tv;
VerboseOn();
cout << "[] test update Start\n";
m[t2] = tv2;
cout << "[] test update Stop\n\n";
VerboseOff();
m.clear();
return 0;
}
>>>>>>>>>>>>>>
Stephen Howe
"Stephen Howe" <stephenPOINThoweATtns-globalPOINTcom> wrote in message
news:OLBPY7Pv...@TK2MSFTNGP15.phx.gbl...