|
Boost : |
From: Lewis Hyatt (lhyatt_at_[hidden])
Date: 2007-07-05 17:05:33
I'm not quite sure I understand the behavior of this simple test of
BOOST_FOREACH:
-------------
#include <vector>
#include <iostream>
#include <boost/foreach.hpp>
using namespace std;
struct noisy_vector : public vector<int> {
explicit noisy_vector(size_t const sz=0, int const val=0) :
vector<int>(sz, val) {
cerr << "\tcontainer was constructed" << endl;
}
noisy_vector(noisy_vector const& other) : vector<int>(other) {
cerr << "\tcontainer was copied" << endl;
}
noisy_vector& operator=(noisy_vector const& other) {
vector<int>::operator=(other);
cerr << "\tcontainer was assigned" << endl;
}
~noisy_vector() {
cerr << "\tcontainer was destructed" << endl;
}
};
inline noisy_vector get_vec(size_t const sz, int const val=0) {
return noisy_vector(sz,val);
}
int main() {
cerr << "TEST 1: LVALUE" << endl;
{
noisy_vector vec = get_vec(5);
cerr << "\tstarting foreach" << endl;
BOOST_FOREACH(int const& i, vec);
}
cerr << endl;
cerr << "TEST2: LVALUE, REFERENCE" << endl;
{
noisy_vector const& vec = get_vec(5);
cerr << "\tstarting foreach" << endl;
BOOST_FOREACH(int const& i, vec);
}
cerr << "TEST 2: RVALUE" << endl;
{
cerr << "\tstarting foreach" << endl;
BOOST_FOREACH(int const& i, get_vec(5));
}
}
-------------
If I compile this, using g++ 3.4.4, with the RVO disabled (using
-fno-elide-constructors), then I get the following output:
-------------
TEST 1: LVALUE
container was constructed
container was copied
container was destructed
container was copied
container was destructed
starting foreach
container was destructed
TEST2: LVALUE, REFERENCE
container was constructed
container was copied
container was destructed
starting foreach
container was destructed
TEST 2: RVALUE
starting foreach
container was constructed
container was copied
container was destructed
container was copied
container was copied
container was destructed
container was destructed
container was destructed
-------------
If I compile it with the RVO enabled, I get the following output:
-------------
TEST 1: LVALUE
container was constructed
starting foreach
container was destructed
TEST2: LVALUE, REFERENCE
container was constructed
starting foreach
container was destructed
TEST 2: RVALUE
starting foreach
container was constructed
container was copied
container was destructed
container was destructed
-------------
So in either case, using BOOST_FOREACH requires one extra copy. Why is
this necessary? I guess the macro is making a copy of the argument to
avoid evaluating it more than once, but isn't it possible just to bind
the temporary to a const reference instead?
Thanks...
-Lewis
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk