By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,952 Members | 1,732 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,952 IT Pros & Developers. It's quick & easy.

returning a vector

P: n/a

Which method is the fastest/best:

std::vector<intfoo1()
{
std::vector<intv;
...
reutun v;
}

std::vector<int>& foo2()
{
static std::vector<intv;
...
reutun v;
}

void foo3(std::vector<int>&v)
{
...
}

I tend to say foo3 is the best, however foo1 and foo2 are more
"convenient". Is there any way of returning a vector as fast as with
foo3?
--
-Gernot
int main(int argc, char** argv) {printf
("%silto%c%cf%cgl%ssic%ccom%c", "ma", 58, 'g', 64, "ba", 46, 10);}

Sep 21 '06 #1
Share this Question
Share on Google+
13 Replies


P: n/a
On 2006-09-21, Gernot Frisch <Me@Privacy.netwrote:
Which method is the fastest/best:

std::vector<intfoo1()
{
std::vector<intv;
...
reutun v;
}

std::vector<int>& foo2()
{
static std::vector<intv;
...
reutun v;
}
Not thread safe, i strongly recommend against this one (regardless of
speed).

void foo3(std::vector<int>&v)
{
...
}

I tend to say foo3 is the best, however foo1 and foo2 are more
"convenient". Is there any way of returning a vector as fast as with
foo3?
You could measure it for yourself, though i doubt that you will see
significant differences (you may get better performance by not using
std::vector, at the cost of convenience).

--
Roland Csaszar ----------- \\\ /// -------------- +43 316 495 2129
Software Development ------ \\\ /// ----------- http://www.knapp.com
KNAPP Logistics Automation - \\V// - mailto:ro************@knapp.com
Sep 21 '06 #2

P: n/a
Gernot Frisch napisał(a):
Which method is the fastest/best:

std::vector<intfoo1()
{
std::vector<intv;
...
reutun v;
}
May be fast as foo3 if the compiler has RVO.
>
std::vector<int>& foo2()
{
static std::vector<intv;
...
reutun v;
}
badly programmed.
>
void foo3(std::vector<int>&v)
{
...
}
preferred.
--
Marcin Gabryszewski
G DATA Software
www.gdata.pl

address:<FirstName><dot><Surname><at><gdata><dot>< pl>
Sep 21 '06 #3

P: n/a

Gernot Frisch wrote:
Which method is the fastest/best:

std::vector<intfoo1()
{
std::vector<intv;
...
reutun v;
}
With a good compiler, the method shown above will be fastest if the
function is used in initialisation:
std::vector<inttest = foo1();

If you use it to reassign, it gets less efficient (but a proposal to
extend the language will bring back efficiency):

std::vector<inttest;
....
test = foo1();
You can regain speed by using std::swap.
>
std::vector<int>& foo2()
{
static std::vector<intv;
...
reutun v;
}
This is not fast at all: The callee will have to copy the entire
vector.
>
void foo3(std::vector<int>&v)
{
...
}
This one will be pretty fast to. The problem is in ease of use and
intent: Initialisation is no longer possible:
std::vector<inttest;
test = foo3();

Also, the code will no longer have the strong exception guarantee (as
presumably foo3 begins by clearing the vector).

I would choose foo1 as the default implementation, and perhaps supply
foo3 as:

void foo3(std::vector<int>&v) { std::vector<inttemp = foo1();
std::swap(v,temp); }.
>
I tend to say foo3 is the best, however foo1 and foo2 are more
"convenient". Is there any way of returning a vector as fast as with
foo3?
/Peter

Sep 21 '06 #4

P: n/a

Gernot Frisch wrote:
Which method is the fastest/best:
I tend to say foo3 is the best, however foo1 and foo2 are more
"convenient". Is there any way of returning a vector as fast as with
foo3?
How about (4):

typedef std::vector<intivect;
std::auto_ptr<ivectfoo()
{
...
}

IMO this is more flexible than the other options. Your option (3) does
not cater for reserving the size for usage in foo... Also, using (4),
the caller can decide whether or not he wants to keep the result. Using
(3) with a swap causes de-allocation of the argument. (4) provides you
with flexibility. The only other concern that you may have is heap
usage, but then you would not be using a vector. (2) is not thread
safe, as previously mentioned - other than that it seems a good option
(if thread safety not required). I don't think (3) is that good,
especially considering the possibility of re-allocation in foo.

Kind regards,

Werner

Sep 21 '06 #5

P: n/a
peter koch <pe***************@gmail.comwrote:
Gernot Frisch wrote:
>std::vector<int>& foo2()
{
static std::vector<intv;
...
reutun v;
}

This is not fast at all: The callee will have to copy the entire
vector.
He is returning a reference to the vector and not the vector itself, so
I think it should be pretty fast.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Sep 21 '06 #6

P: n/a

Marcus Kwok wrote:
peter koch <pe***************@gmail.comwrote:
Gernot Frisch wrote:
std::vector<int>& foo2()
{
static std::vector<intv;
...
reutun v;
}
This is not fast at all: The callee will have to copy the entire
vector.

He is returning a reference to the vector and not the vector itself, so
I think it should be pretty fast.
Yes, but unless you are using a reference variable:

vector<int& x = foo2();

you are doing a copy or initialization same as #1 without possibility
for optimization. This could be efficient given very specific
conditions but in general will not be.

Sep 21 '06 #7

P: n/a
Noah Roberts <ro**********@gmail.comwrote:
Marcus Kwok wrote:
>peter koch <pe***************@gmail.comwrote:
Gernot Frisch wrote:
std::vector<int>& foo2()
{
static std::vector<intv;
...
reutun v;
}

This is not fast at all: The callee will have to copy the entire
vector.

He is returning a reference to the vector and not the vector itself, so
I think it should be pretty fast.

Yes, but unless you are using a reference variable:

vector<int& x = foo2();

you are doing a copy or initialization same as #1 without possibility
for optimization. This could be efficient given very specific
conditions but in general will not be.
Thanks, I see your point and thinking over it, of course you're right.
If foo2() were to be used in some sort of function chaining then it
might be beneficial, but in the context of the OP (returning the vector
to be stored somewhere) a copy will probably be made.

My apologies to peter koch for calling him out when I was wrong.

--
Marcus Kwok
Replace 'invalid' with 'net' to reply
Sep 21 '06 #8

P: n/a

Marcus Kwok wrote:
peter koch <pe***************@gmail.comwrote:
Gernot Frisch wrote:
std::vector<int>& foo2()
{
static std::vector<intv;
...
reutun v;
}
This is not fast at all: The callee will have to copy the entire
vector.

He is returning a reference to the vector and not the vector itself, so
I think it should be pretty fast.
Right. As Noah mentioned, this would be okay if the user initialised
the variable with a reference as in:

std::vector<int>& vec1 = foo2();

But this is dangerous if e.g. the user calls foo2 while there still are
references to the static vector. Now one will change behind your back!
This is the same problem as in a multithreaded environment except that
here you can have the problem without even using threads!

/Peter

Sep 21 '06 #9

P: n/a
Roland.Csaszar wrote:
On 2006-09-21, Gernot Frisch <Me@Privacy.netwrote:
Which method is the fastest/best:

std::vector<intfoo1()
{
std::vector<intv;
...
reutun v;
}

std::vector<int>& foo2()
{
static std::vector<intv;
...
reutun v;
}

Not thread safe, i strongly recommend against this one (regardless of
speed).
Right.
>
void foo3(std::vector<int>&v)
{
...
}

I tend to say foo3 is the best, however foo1 and foo2 are more
"convenient". Is there any way of returning a vector as fast as with
foo3?

You could measure it for yourself, though i doubt that you will see
significant differences (you may get better performance by not using
std::vector, at the cost of convenience).
Huh? Try returning a very large vector or one that is expensive to
copy. Absent the return value optimization and/or the proper client
code to make use of it, foo3 is certainly faster than foo1.

Cheers! --M

Sep 21 '06 #10

P: n/a
peter koch wrote:
Gernot Frisch wrote:
Which method is the fastest/best:

std::vector<intfoo1()
{
std::vector<intv;
...
reutun v;
}

With a good compiler, the method shown above will be fastest if the
function is used in initialisation:
std::vector<inttest = foo1();

If you use it to reassign, it gets less efficient (but a proposal to
extend the language will bring back efficiency):

std::vector<inttest;
...
test = foo1();
You can regain speed by using std::swap.

std::vector<int>& foo2()
{
static std::vector<intv;
...
reutun v;
}

This is not fast at all: The callee will have to copy the entire
vector.

void foo3(std::vector<int>&v)
{
...
}

This one will be pretty fast to. The problem is in ease of use and
intent: Initialisation is no longer possible:
std::vector<inttest;
test = foo3();

Also, the code will no longer have the strong exception guarantee (as
presumably foo3 begins by clearing the vector).

I would choose foo1 as the default implementation, and perhaps supply
foo3 as:

void foo3(std::vector<int>&v) { std::vector<inttemp = foo1();
std::swap(v,temp); }.
Good advice. Here's a quote from from _Efficient C++ Programming_ by
Lippman (http://tinyurl.com/eznwx) that talks about the same things:

----
Matrix mat;
while ( something.more() )
{
mat = something.fetch_mat();
// do something with mat ...

}

mat is set to a different Matrix class object with each iteration. The
programmer could have written

while ( something.more() )
{
Matrix mat = something.fetch_mat();
// do something with mat ...

}

but wished to avoid the construction and destruction of mat with each
loop iteration. Let's rather initialize and destroy it once prior to
and after completion of the loop, the programmer explains, not
realizing that with each iteration, the assignment requires that a
temporary be passed to fetch_mat(), where it is constructed. The
temporary is then copy assigned to mat and destructed. While placing
the definition of mat outside the loop appears more efficient, it is
actually more expensive, resulting in an additional copy assignment
operation with each loop iteration, in addition to the construction and
destruction of a temporary Matrix object.
---

Cheers! --M

Sep 21 '06 #11

P: n/a

peter koch wrote:
Gernot Frisch wrote:
Which method is the fastest/best:

std::vector<intfoo1()
{
std::vector<intv;
...
reutun v;
}

With a good compiler, the method shown above will be fastest if the
function is used in initialisation:
std::vector<inttest = foo1();
I thought the RVO needed a construct like so:

obj fun()
{
return obj();
}

Sep 21 '06 #12

P: n/a
Noah Roberts wrote:
peter koch wrote:
Gernot Frisch wrote:
Which method is the fastest/best:
>
std::vector<intfoo1()
{
std::vector<intv;
...
reutun v;
}
With a good compiler, the method shown above will be fastest if the
function is used in initialisation:
std::vector<inttest = foo1();

I thought the RVO needed a construct like so:

obj fun()
{
return obj();
}
Nope. See the Lippman excerpt I link to above.

Cheers! --M

Sep 21 '06 #13

P: n/a

mlimber wrote:
peter koch wrote:
[snip]
Matrix mat;
while ( something.more() )
{
mat = something.fetch_mat();
// do something with mat ...

}

mat is set to a different Matrix class object with each iteration. The
programmer could have written

while ( something.more() )
{
Matrix mat = something.fetch_mat();
// do something with mat ...

}

but wished to avoid the construction and destruction of mat with each
loop iteration. Let's rather initialize and destroy it once prior to
and after completion of the loop, the programmer explains, not
realizing that with each iteration, the assignment requires that a
temporary be passed to fetch_mat(), where it is constructed. The
temporary is then copy assigned to mat and destructed. While placing
the definition of mat outside the loop appears more efficient, it is
actually more expensive, resulting in an additional copy assignment
operation with each loop iteration, in addition to the construction and
destruction of a temporary Matrix object.
Right! It is always a pleasure when you program with the aim of having
the most readable program that you wind up also having the most
efficient. I can't count how many programs I've seen where an
obfuscation created to improve performance has the opposite effect.

/Peter

Sep 22 '06 #14

This discussion thread is closed

Replies have been disabled for this discussion.