Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Returning class object: is it inefficient?

35 views
Skip to first unread message

Christiano

unread,
Feb 22, 2017, 11:34:30 PM2/22/17
to
I saw this Code in a book[1]:

Date next_Sunday(const Date &d)
{
// access d using d.day(), d.month(), and d.year()
// make new Date to return
}

But that sounded strange to me. I may be wrong, but creating an object
inside a function and then passing it through return forces the calling
function to make a copy of an object, if that object is large it can
make everything inefficient.


[1] http://stroustrup.com/Programming/
ISBN 978-0-321-99278-9
Programming: Principles and Practice using C++ (Second Edition)
In respect to the group and author:
I have the original book,
Using here only a little portion of the book for
educational/research purposes according to fair use.

Robert Wessel

unread,
Feb 22, 2017, 11:43:45 PM2/22/17
to
For such a thing, the common usage would probably be something like:

newdate = nextSunday(olddate);

Inlining that and replacing the object creation, copy, and destruction
with a direct update is a common optimization, for just that reason.
Of course the end result has to be the same as if all that had
actually happened.

Alf P. Steinbach

unread,
Feb 22, 2017, 11:47:47 PM2/22/17
to
On 23.02.2017 05:35, Christiano wrote:
> I saw this Code in a book[1]:
>
> Date next_Sunday(const Date &d)
> {
> // access d using d.day(), d.month(), and d.year()
> // make new Date to return
> }
>
> But that sounded strange to me. I may be wrong, but creating an object
> inside a function and then passing it through return forces the calling
> function to make a copy of an object, if that object is large it can
> make everything inefficient.

Most every compiler nowadays applies Return Value Optimization if it
can. The comment in your code indicates that it can. Then the return
value is constructed directly in storage provided by the calling code,
instead of first being created as temporary and then copied or moved.

With C++17 it's possible that RVO will be required, not just permitted.


Cheers & hth.,

- Alf

Paavo Helde

unread,
Feb 23, 2017, 4:10:55 AM2/23/17
to
On 23.02.2017 6:35, Christiano wrote:
> I saw this Code in a book[1]:
>
> Date next_Sunday(const Date &d)
> {
> // access d using d.day(), d.month(), and d.year()
> // make new Date to return
> }
>
> But that sounded strange to me. I may be wrong, but creating an object
> inside a function and then passing it through return forces the calling
> function to make a copy of an object, if that object is large it can
> make everything inefficient.

1) A 'date' does not look like it could be large.

2) Compilers have been optimizing this kind of stuff for many years
(according to Wikipedia RVO was invented in 1991).

3) Since C++11, we also have rvalue references and move constructors &
assignments, which work best with temporaries like function return
values (otherwise you will need to pepper the code with unwanted noise
like std::move()).

4) If you want to make sure that no copies are made behind the curtains
you can mark the copy constructor and assignment deleted for the class
and rely on the move ctor/assignment instead. This coincidentally means
you should make use more of function return values, not less.

5) As you certainly know, premature optimization is the root of all
evil. Before reducing the readability and maintainability of your code
by doing manual "optimizations" which you *believe* should make the code
faster, take some time to actually *measure* it and see if your beliefs
have any ground.

Bo Persson

unread,
Feb 23, 2017, 7:51:06 AM2/23/17
to
On 2017-02-23 05:35, Christiano wrote:
> I saw this Code in a book[1]:
>
> Date next_Sunday(const Date &d)
> {
> // access d using d.day(), d.month(), and d.year()
> // make new Date to return
> }
>
> But that sounded strange to me. I may be wrong, but creating an object
> inside a function and then passing it through return forces the calling
> function to make a copy of an object, if that object is large it can
> make everything inefficient.
>

Surely, the Date class isn't large.

You must also ask yourself how much "efficiency" you need in your
program, and if the date calculations make any difference.

My guess (just a guess, you have to measure to be sure) is that if you
do less than a million calculations per second, this function will not
show up in the profiler report.

And if you calculate next_Sunday more often than that, the real
optimization might be to ask yourself WHY? Could you perhaps calculate
it once, and reuse the value?


Bo Persson


Christiano

unread,
Feb 24, 2017, 12:21:40 PM2/24/17
to
On 02/23/2017 01:35 AM, Christiano wrote:
> I saw this Code in a book[1]:
>
> Date next_Sunday(const Date &d)
> {
> // access d using d.day(), d.month(), and d.year()
> // make new Date to return
> }
>

I was testing some codes here.

See this C code:

/----------- a1.c -----------------\
#include <stdio.h>

struct house {
int a;
int b;
};

struct house func()
{
struct house e = {2,3};
return e;
}

int main()
{
int num =8;
struct house x = func();

printf("%d %d\n", x.a, x.b);

return 0;
}
\---------------------------------/

Now, see the second version:

/------------- a2.c -----------------------\
#include <stdio.h>

struct house {
int a;
int b;
};

struct house func()
{
return (struct house){2,3};
}

int main()
{
int num =8;
struct house x = func();

printf("%d %d\n", x.a, x.b);

return 0;
}
\--------------------------------------/

The "func" function in the first version locally creates a "struct
house" and then copies it to the "struct house" in the main.

The "func" function in the second version creates the "struct house" in
the main directly.

It is possible to observe this in the generated assembly code using -S
option (gcc/g++).

In C++ things are not different.

For example:

Date new_date_random()
{
Date x = Date{ random_day(), random_month(), random_year() };
return x;
}

VERSUS

Date new_date_random()
{
return Date{ random_day(), random_month(), random_year() };
}

The first version locally creates a "Date" and then copies it to the
"Date" outside. (Assuming here that there was no RVO optimization.)

The second version creates the "Date" outside directly.

That is, this information indicates that:

In situations where we are not receiving references from the object
outside, It is preferable whenever possible to return an unnamed literal
class object.

Paavo Helde

unread,
Feb 24, 2017, 1:25:01 PM2/24/17
to
On 24.02.2017 19:22, Christiano wrote:

>
> I was testing some codes here.

Are you sure you compiled with optimization flags like -O2 ? This whole
thread is all about optimizations, for testing them you need to switch
them on.


0 new messages