473,473 Members | 1,947 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

Returning by value or reference

mjm
Folks,

Stroustrup indicates that returning by value can be faster than
returning by reference but gives no details as to the size of the
returned object up to which this holds.

My question is up to which size m would you expect

vector<double> returns_by_value()
{
int m=...;
vector<double> x(m);
return x;
}
to be faster than
vector<double>& returns_by_reference()
{
int m=...;
vector<double>* x=new vector<double>(m);
return *x;
}
Jul 19 '05 #1
9 11884
>Stroustrup indicates that returning by value can be faster than
returning by reference
I can see no such case, but I may be mistaken.
My question is up to which size m would you expect

vector<double> returns_by_value()
{
int m=...;
vector<double> x(m);
return x;
}
to be faster than
vector<double>& returns_by_reference()
{
int m=...;
vector<double>* x=new vector<double>(m);
return *x;
}


It depends.

First, the return_by_reference() function is a bomb. The one who will
call it will have absolutly _no_ idea he has to delete the object.
You would be better doing something like

static vector<double> x(m);
return x;

But then all callers will be bound to the same object. This is not
good practice : you cannot return a reference to something you didn't
have at first.

Next, using the heap is almost always slower than using the stack, so
I would expect the second function to be slower in any case.

What`s more, the compiler could optimize the copy returned by
returns_by_value(), so you would end up only creating the object once,
and on the stack. This version will almost always be faster than the
second one.

Where did you see that? Maybe the context was different?
Jonathan

Jul 19 '05 #2
sp*******@yahoo.com (mjm) wrote in message news:<f3**************************@posting.google. com>...
Stroustrup indicates that returning by value can be faster than
returning by reference but gives no details as to the size of the
returned object up to which this holds. My question is up to which size m would you expect

vector<double> returns_by_value()
{
int m=...;
vector<double> x(m);
return x;
}
First, the efficiency of this function depends on the compiler. Some
perform what is called named return value optimization (NRVO), which
is related to the fact that your returned value has a name ("x").
However, many more compilers support unnamed return value optimization
(RVO), which has the additional requirement that the returned object
be an unnamed temporary:

vector<double> returns_by_value () {
int m=...;
return vector<double>(m);
}
to be faster than
vector<double>& returns_by_reference()
{
int m=...;
vector<double>* x=new vector<double>(m);
return *x;
}


Never return a reference to a dynamically-allocated object which the
caller is expected to clean up, not even as an example. You should
return an object by reference only if that object exists before the
function call, i.e., if it's global, static, or passed in by pointer
or reference (including the "this" pointer for member functions).

This is important, because your question is purely academic (read:
pointless) if you're not going to use an example of code you might
reasonably use in an actual program. In an actual program, the obvious
alternative to returning by value is to take a pointer or reference to
the object and modify it in-place, like so:

vector<double> &assigns_by_reference (vector<double> &x) {
int m=...;
x.assign(m, 0.0);
return x;
}

It's only fair to compare this real-world code to returns_by_value();
that is what I will do.

So, assigns_by_reference() requires that its argument be constructed
already, whereas returns_by_value() does not:

// (a)
vector<double> foo; // default-construct
assigns_by_reference(foo); // assign new value

// (b)
vector<double> bar = returns_by_value(); // construct w/ new value

If the compiler supports [N]RVO, (b) may actually be negligibly faster
than (a). [N]RVO allows the compiler to construct the returned value
*inside* "bar", thus eliminating (we call it "eliding") a copy
constructor or destructor call, as well as any code dealing with
returning a value (since the returned value is used directly as
"bar").

HOWEVER....

If the compiler doesn't support [N]RVO, then (b) may involve an
additional copy construction and destruction of the temporary. The
same is true if the code involves assignment, as [N]RVO applies only
to construction:

// (c)
vector<double> bar; // default-construct
bar = returns_by_value(); // assign new value

As you guessed, exactly how slow this is depends on the size of the
returned vector. Unfortunately, the actual "m" at which (b) (without
[N]RVO) or (c) becomes slower than (a) is dependent on the compiler.
The only real way to find out is to run it with various values for "m"
and see what happens.

Note: You can replace (c) with this:

// (d)
vector<double> foo; // default-construct
returns_by_value().swap(foo); // swap old and new values

This should be roughly the same as (a), and about as fast, too.

Hope that helps!

- Shane
Jul 19 '05 #3

"mjm" <sp*******@yahoo.com> wrote in message
news:f3**************************@posting.google.c om...
Folks,

Stroustrup indicates that returning by value can be faster than
returning by reference but gives no details as to the size of the
returned object up to which this holds.


I was curious of this myself a while back so I ran a test of my own.

I don't have exact test results any more but you can recreate. What I did
was create a struct:

struct fvector2
{
float c[2];
};

struct fvector3
{
float c[3];
};
First I executed a function returning each of these by value and then by
ref. I timed called them around 1million times each.

My result was the fvector2 was faster returning by value and fvector3 was
faster by reference. I had all -O3 on GCC 3.2.3, your mileage may vary.

Jeff
Jul 19 '05 #4
mjm wrote:
Stroustrup indicates that
Please cite and quote Stroustrup.
returning by value can be faster
than returning by reference
but gives no details as to
the size of the returned object up to which this holds.

My question is up to which size m would you expect

vector<double> returns_by_value(int m) {
vector<double> x(m);
return x;
}

to be faster than

vector<double>& {
vector<double>* x = new vector<double>(m);
return *x;
}


You would be obliged to write

vector<double>& r = returns_by_reference(int m);
// use r
delete &r;

This is dangerous because you would create a memory leak
if the thread of execution failed to pass through the delete.
You would barely notice (you probably couldn't measure)
the overhead for the extra new and delete for a single invocation.
You would probably need to embed it in vary a tight loop
over small vectors.

Jul 19 '05 #5
mjm
Thanks for all the valuable information.
My vectors typically have dimension 20-80 doubles.

I understand the deallocation problem.
Actually in my own program the question how to return does not occur
in critical loops so I could and probably should return by value.

There is a nasty problem as follows: the constructors of the objects
(vectors, matrices) themselves allocate memory on the heap. So you
cannot escape heap allocation even if you return by value.

Is there any way to get around this if you want to dynamically
allocate arrays possibly ragged (triangular matrices for example).

I understand that you could avoid returning anything and instead write
into existing objects. But this makes really ugly C-like code.

The section of Stroustrup (anniversary edition) is 11.6, p283.
There is more than one page of information on the problem so I won't
provide a detailed quote.
Jul 19 '05 #6
sp*******@yahoo.com (mjm) wrote in message news:<f3**************************@posting.google. com>...
Thanks for all the valuable information.
My vectors typically have dimension 20-80 doubles.
...
The section of Stroustrup (anniversary edition) is 11.6, p283.
There is more than one page of information on the problem so I won't
provide a detailed quote.


A better reference is TC++PL3 22.4.7. That's the technique for
eliminating spurious temporaries used by most modern vector/matrix
libraries (see my C++ page and/or the libraries FAQ for examples of
such libraries).

- Bjarne Stroustrup, http://www.research.att.com/~bs
Jul 19 '05 #7
mjm
Thanks for the response and C++.
A better reference is TC++PL3 22.4.7. That's the technique for
eliminating spurious temporaries used by most modern vector/matrix
libraries (see my C++ page and/or the libraries FAQ for examples of
such libraries).

- Bjarne Stroustrup, http://www.research.att.com/~bs

Jul 19 '05 #8
mjm
Thanks for the response and C++.
A better reference is TC++PL3 22.4.7. That's the technique for
eliminating spurious temporaries used by most modern vector/matrix
libraries (see my C++ page and/or the libraries FAQ for examples of
such libraries).

- Bjarne Stroustrup, http://www.research.att.com/~bs

Jul 19 '05 #9
Returning by reference may involve some bookkeeping. If reference counting
is done than I'd think returning by value is faster for pointer-sized values
like long, Int32, etc. Does this concern .NET?

"mjm" <sp*******@yahoo.com> wrote in message
news:f3**************************@posting.google.c om...
Folks,

Stroustrup indicates that returning by value can be faster than
returning by reference but gives no details as to the size of the
returned object up to which this holds.

My question is up to which size m would you expect

vector<double> returns_by_value()
{
int m=...;
vector<double> x(m);
return x;
}
to be faster than
vector<double>& returns_by_reference()
{
int m=...;
vector<double>* x=new vector<double>(m);
return *x;
}

Jul 19 '05 #10

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

Similar topics

6
by: Krackers | last post by:
How do you write a function which returns a reference to an array. I can only get a function to return a copy of the array itself. I've had a look at some other threads in this group an the return...
4
by: Patrick | last post by:
I want to achieve the following behaviour but I am having trouble getting there...bare with me im knew to c++ , so its probably rather trivial! To have a class ClassA, and composed within this...
18
by: cppaddict | last post by:
Hi, Is it considered bad form to have the subscript operator return a const reference variable? If not, what is the proper way to do it? My question was prompted by the code below, my...
19
by: JKop | last post by:
When I compile and run the following on my system: #include <iostream> static int hello = 78; int ReturnValue(void) {
11
by: JKop | last post by:
AnyClass Blah() { AnyClass poo; return poo; } As we all know, in the above, the compiler is entitled to:
25
by: Victor Bazarov | last post by:
In the project I'm maintaining I've seen two distinct techniques used for returning an object from a function. One is AType function(AType const& arg) { AType retval(arg); // or default...
13
by: Matthias Kaeppler | last post by:
Hi, I was wondering why library implementors often make getter functions return strings by value (copies). For example, in boost::filesystem the leaf() function returns an std::string by value....
23
by: pauldepstein | last post by:
Below is posted from a link for Stanford students in computer science. QUOTE BEGINS HERE Because of the risk of misuse, some experts recommend never returning a reference from a function or...
8
by: darren | last post by:
Hi everybody, have a quick look at this code: ===== ===== int main(void) { string msg; makeString(msg); cout << "back in main, result = " << msg << endl;
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
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
1
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
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,...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...
0
muto222
php
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.