C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Curious about my Diagnosis

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
al.anon@gmail.com
Guest





PostPosted: Fri Apr 15, 2005 7:23 am    Post subject: Curious about my Diagnosis Reply with quote



I was learning some more of the STL and ran across for_each when I came
up with a simple example to use it:

#include <iostream>
#include <vector>
#include <algorithm>

class Dog {
public:
Dog(int x) : id(x){ std::cout << id << " livesn"; }
~Dog() { std::cout << id << " diedn"; }
void speak() {
std::cout << "Bark " << id << "n";
}
private:
int id;

};


int main() {
size_t dogs = 5;

std::vector pound.reserve(dogs);
for (size_t i =0; i < dogs; i++) {
pound.push_back(Dog(i));
}


std::for_each(pound.begin(),pound.end(),std::mem_fun_ref(&Dog::speak));

}


I get some strange output when I run this code:

0 lives
0 died
1 lives
1 died
2 lives
2 died
3 lives
3 died
4 lives
4 died
Bark 0
Bark 1
Bark 2
Bark 3
Bark 4
0 died
1 died
2 died
3 died
4 died


I think I may understand it however. Does pound.push_back(Dog(i)) make
a temp Dog object that is then copied to the vector with the default
copy constructor, hence not calling the constructor again ? This would
explain the mismatch between number of constructor and number of
destructor calls.

If so is there any way to get rid of the temporary object ? I know I
could store pointers in the std::vector but then I need to delete them
before the vector goes out of scope and I can't store an auto_ptr in
the vector to take care of the deletion for me because of the
"assignment takes possession" issue of auto_ptr.

Just curious if there is an elegant solution, perhaps a way of calling
for_each on the vector to delete the objects whose pointers it holds.

Al


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maxim Yegorushkin
Guest





PostPosted: Fri Apr 15, 2005 9:23 am    Post subject: Re: Curious about my Diagnosis Reply with quote



On 15 Apr 2005 03:23:21 -0400, [email]al.anon (AT) gmail (DOT) com[/email] <al.anon (AT) gmail (DOT) com> wrote:

Quote:
I was learning some more of the STL and ran across for_each when I came
up with a simple example to use it:

#include <iostream
#include #include
class Dog {
public:
Dog(int x) : id(x){ std::cout << id << " livesn"; }
~Dog() { std::cout << id << " diedn"; }
void speak() {
std::cout << "Bark " << id << "n";
}
private:
int id;

};


int main() {
size_t dogs = 5;

std::vector pound.reserve(dogs);
for (size_t i =0; i < dogs; i++) {
pound.push_back(Dog(i));
}


std::for_each(pound.begin(),pound.end(),std::mem_fun_ref(&Dog::speak));

}

[]

Quote:
I think I may understand it however. Does pound.push_back(Dog(i)) make
a temp Dog object that is then copied to the vector with the default
copy constructor, hence not calling the constructor again ? This would
explain the mismatch between number of constructor and number of
destructor calls.

Just add these to see the whole picture:

Dog(Dog const& d) : id(d.id) { std::cout << id << " copiedn"; }
Dog& operator=(Dog const& d) { std::cout << (id = d.id) << "
copiedn"; }

Quote:
If so is there any way to get rid of the temporary object ? I know I
could store pointers in the std::vector but then I need to delete them
before the vector goes out of scope and I can't store an auto_ptr in
the vector to take care of the deletion for me because of the
"assignment takes possession" issue of auto_ptr.

Using memory allocation to avoid temporaries may cost you more.

Quote:
Just curious if there is an elegant solution, perhaps a way of calling
for_each on the vector to delete the objects whose pointers it holds.

A compiler may optimize the temporaries away.

Nevertheless, use a profiler to see if those temporaries are the source of
any hot spots before trying to get rid of them.

--
Maxim Yegorushkin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Thomas Maeder
Guest





PostPosted: Fri Apr 15, 2005 9:25 am    Post subject: Re: Curious about my Diagnosis Reply with quote



"al.anon (AT) gmail (DOT) com" <al.anon (AT) gmail (DOT) com> writes:

Quote:
#include <iostream

#include
Quote:
#include <vector
#include
class Dog {
public:
Dog(int x) : id(x){ std::cout << id << " livesn"; }
~Dog() { std::cout << id << " diedn"; }
void speak() {
std::cout << "Bark " << id << "n";
}
private:
int id;

};


int main() {
size_t dogs = 5;

std::vector pound.reserve(dogs);
for (size_t i =0; i < dogs; i++) {
pound.push_back(Dog(i));
}


std::for_each(pound.begin(),pound.end(),std::mem_fun_ref(&Dog::speak));

}


I get some strange output when I run this code:

0 lives
0 died
1 lives
1 died
2 lives
2 died
3 lives
3 died
4 lives
4 died
Bark 0
Bark 1
Bark 2
Bark 3
Bark 4
0 died
1 died
2 died
3 died
4 died


I think I may understand it however. Does pound.push_back(Dog(i)) make
a temp Dog object that is then copied to the vector with the default
copy constructor, hence not calling the constructor again?

The meaning is right, but the wording isn't quite. The generated
copy-constructor is also a constructor.


Quote:
This would
explain the mismatch between number of constructor and number of
destructor calls.

The mismatch is in the output you generate, not in the numbers of
constructors and destructor calls. Implement the copy-constructor
yourself and add a statement generating output, and you'll see.


Quote:
If so is there any way to get rid of the temporary object ?

I think that the compiler is allowed to optimize the temporary object
away. You might try increasing the optimization settings of your
compiler.

Apart from that, you can't do much (except creating the objects
dynamically, which you mention later). The STL containers deal with
values, not references.


Quote:
I know I could store pointers in the std::vector but then I need to
delete them before the vector goes out of scope and I can't store an
auto_ptr in the vector to take care of the deletion for me because
of the "assignment takes possession" issue of auto_ptr.

boost::shared_ptr copes with this issue very well.


Quote:
Just curious if there is an elegant solution, perhaps a way of calling
for_each on the vector to delete the objects whose pointers it holds.

Elegance is in the eye of the beholder.

Unless the temporary objects are a real problem, the present solution
is elegant already IMHO.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Stefan Näwe
Guest





PostPosted: Fri Apr 15, 2005 9:27 am    Post subject: Re: Curious about my Diagnosis Reply with quote

[email]al.anon (AT) gmail (DOT) com[/email] schrieb:
Quote:
[...]
If so is there any way to get rid of the temporary object ? I know I
could store pointers in the std::vector but then I need to delete them
before the vector goes out of scope and I can't store an auto_ptr in
the vector to take care of the deletion for me because of the
"assignment takes possession" issue of auto_ptr.

Why not use a std::vector<boost::shared_ptr ?

Stefan

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Mary K. Kuhner
Guest





PostPosted: Sat Apr 16, 2005 12:04 am    Post subject: Re: Curious about my Diagnosis Reply with quote

In article <1113531770.821786.156210 (AT) z14g2000cwz (DOT) googlegroups.com>,
[email]al.anon (AT) gmail (DOT) com[/email] <al.anon (AT) gmail (DOT) com> wrote:

Quote:
I think I may understand it however. Does pound.push_back(Dog(i)) make
a temp Dog object that is then copied to the vector with the default
copy constructor, hence not calling the constructor again ? This would
explain the mismatch between number of constructor and number of
destructor calls.

Yes, the copy constructor is used to put the Dog in the vector.
Scott Meyer's _Effective STL_ has a really nice discussion of the way
the STL copies things around. For objects that are not expensive
to copy, it's often best just to accept this behavior.

Quote:
If so is there any way to get rid of the temporary object ? I know I
could store pointers in the std::vector but then I need to delete them
before the vector goes out of scope and I can't store an auto_ptr in
the vector to take care of the deletion for me because of the
"assignment takes possession" issue of auto_ptr.

Boost's shared_ptr works well in this context, and if your Dogs
are expensive to copy, this may be the best solution. It seems
much more foolproof to me than writing something to delete the
Dog*'s in the vector--you could forget to do that easily, whereas
shared_ptr doesn't forget, and also won't delete a Dog when there
is still someone looking at it.

Mary Kuhner [email]mkkuhner (AT) eskimo (DOT) com[/email]

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Carl Barron
Guest





PostPosted: Sat Apr 16, 2005 5:39 pm    Post subject: Re: Curious about my Diagnosis Reply with quote

Mary K. Kuhner <mkkuhner (AT) kingman (DOT) gs.washington.edu> wrote:

Quote:
It seems
much more foolproof to me than writing something to delete the
Dog*'s in the vector--you could forget to do that easily, whereas
shared_ptr doesn't forget, and also won't delete a Dog when there
is still someone looking at it.

also something like this is a problem with raw ptrs.
std::vector<Dog *> dogs;

std::vector<Dog *> it = std::remove_if(dogs,begin(),dogs.end(),
some_functor());

all the removed Dog *'s are subject to leaking...
it probably looks something like this
which is not optimal but expository...

template <class For,class Pred>
For remove_if(For begin,For end,Pred pred)
{
For out(begin);
for(;begin!=endl;++begin)
{
if(!pred(*begin))
{
*out = *begin;
++out;
}
}
return out;
}

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Paavo Helde
Guest





PostPosted: Sun Apr 17, 2005 2:22 pm    Post subject: Re: Curious about my Diagnosis Reply with quote

"al.anon (AT) gmail (DOT) com" <al.anon (AT) gmail (DOT) com> wrote in
news:1113531770.821786.156210 (AT) z14g2000cwz (DOT) googlegroups.com:

Quote:
std::vector<Dog> pound;
pound.reserve(dogs);
for (size_t i =0; i < dogs; i++) {
pound.push_back(Dog(i));
}
[...]
If so is there any way to get rid of the temporary object ?

As already mentioned, the compiler may optimize away the copy. If this is
not the case and the Dog objects are very expensive to copy, then you
might be able to define a fast default ctor and a fast swap() operation
for them and swap them into the vector:

for (size_t i =0; i < dogs; i++) {
Dog a_dog(i); // construct once
pound.push_back(Dog());
pound.back().swap(a_dog); // swap into place
}

(The initial reserve() call you already have becomes more essential in
this case).

However, I would not bother doing this unless the profiler shows a
bottleneck here.

Paavo

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.