473,414 Members | 1,690 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,414 software developers and data experts.

map inserts and efficiency

Consider the following:

// Contrast different ways of inserting into a map

#include <map>
#include <iostream>

using namespace std;

struct A
{
A () {cout << "ctor\n";}
A (const A& a) {cout << "copy ctor\n";}
A& operator= (const A& a) {cout << "op=\n"; return *this;}
};

typedef map<int,A> IAMap;
typedef IAMap::value_type IAMVal;

int main()
{
cout << "\nm1[0] = ...\n";
IAMap m1;
m1[0] = A();

cout << "\nm2.insert(IAMVal...)\n";
IAMap m2;
m2.insert(IAMVal(0,A()));
}

// end of code

The output is:

m1[0] = ...
ctor
copy ctor
copy ctor
ctor
op=

m2.insert(IAMVal...)
ctor
copy ctor
copy ctor

// end of output

First of all, are the two copy ctor calls both necessary? I gather that
one occurs when constructing the temporary IAMVal and a second occurs
when copying that temporary into the map. Can a smart compiler
eliminate (elide?) the construction of the temporary? (My version of
gcc with maximum optimiztion will not do so.)

On a related note, in Scott Meyers's "Effective STL" he compares these
two approaches in the contexts of inserts (new key) vs. updates
(existing key with new data). He states about inserts, "Efficiency
considerations thus lead us to conclude that insert is preferable to
operator[] when adding an element to a map..." And so it would appear
by simply counting the number of operations above.

But now suppose my data type contains a vector which is empty for a
default constructed object and I want to insert an object whose vector
isn't empty. Comparing the two approaches and paying attention only to
operations which involve the nonempty vector (since this is ostensibly
more work), the insert approach involves two copies of the nonempty
vector while the [] appraoch involves only one assignment of the
nonempty vector. (Unless of course the compiler can eliminate one of
the copies.) Am I looking at this right?

Thanks,
Mark
Jan 27 '06 #1
4 2444

"Mark P" <us****@fall2005REMOVE.fastmailCAPS.fm> wrote in message
news:fj******************@newssvr29.news.prodigy.n et...
Consider the following:

// Contrast different ways of inserting into a map

#include <map>
#include <iostream>

using namespace std;

struct A
{
A () {cout << "ctor\n";}
A (const A& a) {cout << "copy ctor\n";}
A& operator= (const A& a) {cout << "op=\n"; return *this;}
};

typedef map<int,A> IAMap;
typedef IAMap::value_type IAMVal;

int main()
{
cout << "\nm1[0] = ...\n";
IAMap m1;
m1[0] = A();

cout << "\nm2.insert(IAMVal...)\n";
IAMap m2;
m2.insert(IAMVal(0,A()));
}

// end of code

The output is:

m1[0] = ...
ctor
copy ctor
copy ctor
ctor
op=

m2.insert(IAMVal...)
ctor
copy ctor
copy ctor

// end of output

First of all, are the two copy ctor calls both necessary? I gather that
one occurs when constructing the temporary IAMVal and a second occurs when
copying that temporary into the map. Can a smart compiler eliminate
(elide?) the construction of the temporary? (My version of gcc with
maximum optimiztion will not do so.)

On a related note, in Scott Meyers's "Effective STL" he compares these two
approaches in the contexts of inserts (new key) vs. updates (existing key
with new data). He states about inserts, "Efficiency considerations thus
lead us to conclude that insert is preferable to operator[] when adding an
element to a map..." And so it would appear by simply counting the number
of operations above.

But now suppose my data type contains a vector which is empty for a
default constructed object and I want to insert an object whose vector
isn't empty. Comparing the two approaches and paying attention only to
operations which involve the nonempty vector (since this is ostensibly
more work), the insert approach involves two copies of the nonempty vector
while the [] appraoch involves only one assignment of the nonempty vector.
(Unless of course the compiler can eliminate one of the copies.) Am I
looking at this right?


I'm no expert with this stuff, but:

Yes, I believe the compiler is allowed to elide a copy
ctor call as long as the resulting behavior is the same
('efficiency' not being part of 'behavior'). However,
since your copy ctor includes code for output, it must
be called, since its behavior differs from a default
copy ctor. Rather than your 'high level' analysis using
outputs, try taking them out and watching with a debugger.
If your compiler does elide the calls, stepping through
the code should reflect that.

I don't know if there are circumstances where a compiler
could elide a call to operator=() though.

HTH,
-Mike
Jan 27 '06 #2
Mark P wrote:

[ ... ]
m1[0] = A();
[ ... ]
m2.insert(IAMVal(0,A()));
[ ... ]
First of all, are the two copy ctor calls both necessary?
No. According to the standard ($12.8/15), when a temporary class object
is copied using a copy ctor, and the object and the copy have the same
cv-qualification, the compiler is allowed to elide the copy ctor, even
if the copy ctor (and/or dtor) has side effects.

[ ... ]
On a related note, in Scott Meyers's "Effective STL" he compares these
two approaches in the contexts of inserts (new key) vs. updates
(existing key with new data). He states about inserts, "Efficiency
considerations thus lead us to conclude that insert is preferable to
operator[] when adding an element to a map..." And so it would appear
by simply counting the number of operations above.


When you use operator[], it has to return a reference to some object,
so it has to have an object to return a reference to -- which means
default constructing an object. Once you've created that default
object, you immediately replace it with a copy of the other object
being inserted. Even a compiler that can sometimes elide the use of the
copy ctor might easily have difficulty doing so in this situation.

--
Later,
Jerry.

Jan 28 '06 #3
What you say about insert vs. operator[] is correct, but I think the
potentially surprising thing here is that even operator[] on its own
(without the assignment) yields two calls to the copy constructors.
That is to say,
m1[0];
produces:
ctor
copy ctor
copy ctor

This is because libstdc++'s implementation of operator[] does the
following:
1) Constructs a temporary A object (ctor call)
2) Uses the temporary A to construct temporary IAMVal (copy ctor)
3) Calls insert with the temporary IAMVal (copy ctor when insertion
occurs)

This seems inefficient but the implementation is specified by the
standard (23.3.1.2).

What's worse is that the compiler can't elide either of the copy
constructors, because in both cases the temporaries have been bound to
const references at the point the copy construction occurs. Consider
the difference between these two functions:

void f(const A &a) {
// even if 'a' refers to a temporary, eliding impossible
// here. copy ctor used
A b = a;
}
void f() {
A b = A(); // eliding possible, so ctor called just once
}

...

f((A())); // temporary bound to const ref. - calls ctor and copy ctor
f(); // only default ctor is called
So the problem is with the STL, not the compiler. It would be nice to
have a map::operator[] that just called the default constructor in the
case that the entry needed to be created, but the standard doesn't
permit it.

Have I got that right?

Jan 28 '06 #4
I think you are looking at it right, but I doubt you'll get the
compiler to eliminate any of the copying.
I usually take the approach that any object in an STL container will
get copied and assigned quite a bit, and so try to make the object
itself as lightweight as possible.

In your case, how about making the vector reference-counted? That way
you could copy or assign the reference very cheaply. However you would
need to check that the reference was unique before any operation that
modified the vector, and if not then copy it prior to the operation
(this is the approach that many std::string implementations take). It's
quite a bit of work and not necessarily appropriate to your situation,
but worth considering.

Jan 28 '06 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Chris Ochs | last post by:
First of all, we are still running sapdb at the moment but are in the process of moving to postgresql, so it seemed a good idea to post this type of question here. In our environment we have...
7
by: Steven D.Arnold | last post by:
How good is Postgres' performance for massive simultaneous insertions into the same heavily-indexed table? Are there any studies or benchmarks I can look at for that? I understand Postgres uses...
92
by: Dave Rudolf | last post by:
Hi all, Normally, I would trust that the ANSI libraries are written to be as efficient as possible, but I have an application in which the majority of the run time is calling the acos(...)...
1
by: Tomás | last post by:
dynamic_cast can be used to obtain a pointer or to obtain a reference. If the pointer form fails, then you're left with a null pointer. If the reference form fails, then an exception is thrown....
335
by: extrudedaluminiu | last post by:
Hi, Is there any group in the manner of the C++ Boost group that works on the evolution of the C language? Or is there any group that performs an equivalent function? Thanks, -vs
2
by: simonZ | last post by:
I create a transaction: sqlTran=sqlConn.BeginTransaction(IsolationLevel.Serializable); Then, I insert some data into report table with sqlCommand object: oCmd = new...
19
by: vamshi | last post by:
Hi all, This is a question about the efficiency of the code. a :- int i; for( i = 0; i < 20; i++ ) printf("%d",i); b:- int i = 10;
9
by: OldBirdman | last post by:
Efficiency I've never stumbled on any discussion of efficiency of various methods of coding, although I have found posts on various forums where individuals were concerned with efficiency. I'm...
5
by: want.to.be.professer | last post by:
For OO design, I like using virtual member function.But considering efficiency, template is better. Look at this program, class Animal { public: virtual void Walk() = 0; }; class Dog
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.