Returning a Struct from a Function

A

alex.j.k2

Hello, newbie here.

I'd like to know if there is a way to return a structure from a
function, without creating any other intermediate variables. Also,
this should be done such that the function can still be declared as
inline.

More precisely, given the structure:

struct TwoFields {
int Field_one;
int Field_two;
}

I want a function like the following one, but without the
extra declaration, "TwoFields myReturnStruct;":

inline TwoFields ReturnMyFields(int myInt) {

TwoFields myReturnStruct;

myReturnStruct.Field_one = myInt/2;
myReturnStruct.Field_two = myInt%2;

return myReturnStruct;
}

The only reason I want this is speed efficiency, so if this is not
worth doing please let me know.

Alex
 
J

john

(e-mail address removed) dixit:
Hello, newbie here.

I'd like to know if there is a way to return a structure from a
function, without creating any other intermediate variables. Also,
this should be done such that the function can still be declared as
inline.

The usual way is to pass a reference to the struct (as a parameter) in
which you want to put the return value (the same for vector, list, ...)
 
A

alex.j.k2

(e-mail address removed) dixit:



The usual way is to pass a reference to the struct (as a parameter) in
which you want to put the return value (the same for vector, list, ...)

OK, that certainly works.

But is this the only way to do it?

What if I have a lot of code which returns a struct (or vector,
etc..) by creating an intermediate variable in the function; and I do
not want to modify all the occurrences of the function in the code,
only the function itself.

Can I eliminate the creation of the extra variable, while returning
the struct (but not as a parameter) ?

Also, thanks for the quick reply.

Alex
 
P

peter koch

Hello, newbie here.

  I'd like to know if there is a way to return a structure from a
function, without creating any other intermediate variables. Also,
this should be done such that the function can still be declared as
inline.

Yes. Any ordinary function will likely do so. The compiler is allowed
to optimise this special case that has been given the name (N)RVO for
(Named) Return Value Optimisation and all recent compilers should be
able to use this strategy.
  More precisely, given the structure:

struct TwoFields {
   int Field_one;
   int Field_two;

}

I want a function like the following one, but without the
extra declaration, "TwoFields myReturnStruct;":

inline TwoFields ReturnMyFields(int myInt) {

TwoFields myReturnStruct;

myReturnStruct.Field_one = myInt/2;
myReturnStruct.Field_two = myInt%2;

return myReturnStruct;

}
This looks fine to me.
  The only reason I want this is speed efficiency, so if this is not
worth doing please let me know.
I can sympathise with your attitude - I used to think that way
myself. But seriously: do you believe that the difference in execution
time for that function is going to make any difference?

/Peter
 
A

alex.j.k2

Yes. Any ordinary function will likely do so. The compiler is allowed
to optimise this special case that has been given the name (N)RVO for
(Named) Return Value Optimisation and all recent compilers should be
able to use this strategy.

If I parse this correctly, you are saying that a good compiler will
not actually make the extra allocation if it is not needed, even if I
use the code in the initial post. Is that correct?

I can sympathise with your attitude - I used to think that way
myself. But seriously: do you believe that the difference in execution
time for that function is going to make any difference?

I genuinely do not know, but I thought it a good thing to know.
I do use the function deep inside nested loops in a computation
that takes days if not weeks, so I am trying to speed up genuine
bottlenecks, not just doing it for the sake of frivolous efficiency.

Thank you for the reply,
Alex
 
A

alex.j.k2

* (e-mail address removed):


In general one should not optimize prematurely. However, designing a
program so that it needlessly copies megabytes of data in function
calls is ungood. The advice about optimization is really about
micro-optimization, not about not applying common sense.

Yes. In my defense, I did not do something as dumb as passing
megabytes of data by value instead of reference. The values passed
around are just one integer and a two integer struct, as in my
example. Google led me to believe that there is not much speed
difference in passing by reference instead of value for such small
data -- sometimes (for some compilers) passing by value may be faster,
Google said.
For a large vector or something like that, the simplest technique is
to provide 2 variants of your function:

void getDataset( std::vector<Whatever>& result )
{
std::vector<Whatever> tempResult;
// Fill in tempResult here, then:
tempResult.swap( result );
}

inline std::vector<Whatever> dataset()
{
std::vector<Whatever> result;
getDataset( result );
return result;
}

Now users can just use the simple function call notation for
dataset(), until they discover that hey, this is a performance
bottleneck, at which time they measure, find that it's your dataset()
that's doing a lot of copying, and then switch to using getDataset().

That's a useful technique to know.
But that may in reality never occur, because a modern compiler is
likely to do Return Value Optimization, where a call of dataset()
produces machine code almost like it was getDataset that was called
directly -- the "almost" is because RVO is more efficient than that.

I just found out about (N)RVO today, in this thread. From a quick
search it seems that my compiler (GNU GCC) does (N)RVO, so there was
little reason for my initial worry.

But, wow, did I get more than I bargained for bellow! : )
If one is pessimistic enough to believe that (1) the user's compiler
won't do RVO, and (2) the conditions for the performance problem
(enough data, called repeatedly) will be present, and (3) clean
notation like the dataset() function is required, then the only
recourse is to implement something like RVO manually. Usually that's
called "move semantics". For example, Andrei Alexandrescu has
implemented a std::vector replacement with move semantics (part of his
YASLI which it seems will never be completed), plus a general
framework for move semantics called Mojo. As another example, a
number of people were involved in implementing two smart pointers
called move_ptr for a Boost proposal; it was not accepted but still
the code could help. As a third example, Howard Hinnant has
implemented an emulation of C++0x unique_ptr (however, older compilers
such as MSVC 7.1 don't like that code).

But if you don't want that new-fangled stuff, then there's nothing
very wrong in this context with just using std::auto_ptr, which is a
smart pointer with ownership transfer, almost like move semantics.
That usage can, if needed, be wrapped in a little class. The downside
is that using a smart pointer as result type is that (A) the notation
is a little bit less clean (after all, it's a pointer), and (B) it
involves an additional dynamic allocation and indirection.

Wow, thanks for that. It will take me a while to digest it.
Fortunately, my problem is simple enough that I do not need to do RVO
manually. But I might need it for other parts of my program, so I've
saved your text for future reference.

Thank you!

Alex
 
G

Gianni Mariani

Hello, newbie here.

I'd like to know if there is a way to return a structure from a
function, without creating any other intermediate variables. Also,
this should be done such that the function can still be declared as
inline.

More precisely, given the structure:

struct TwoFields {
int Field_one;
int Field_two;
}

I want a function like the following one, but without the
extra declaration, "TwoFields myReturnStruct;":

inline TwoFields ReturnMyFields(int myInt) {

TwoFields myReturnStruct;

myReturnStruct.Field_one = myInt/2;
myReturnStruct.Field_two = myInt%2;

return myReturnStruct;
}

The only reason I want this is speed efficiency, so if this is not
worth doing please let me know.

Premture optimization alert !

BTW - if you really want to do this - imho this is the easy way - and
BTW - RVO will prolly happen.

TwoFields & f = ReturnMyFields(v);

Notice there is a temporary returned which is getting bound to a
reference. In theory, this will only get constructed once - in the
function ReturnMyFields; If your compiler is really smart, (and olot of
them are) it will never hit memory and exist only in registers.

Unless you "know" this is an issue for you, don't bother worrying about it.
 
E

Erik Wikström

Premture optimization alert !

BTW - if you really want to do this - imho this is the easy way - and
BTW - RVO will prolly happen.

TwoFields & f = ReturnMyFields(v);

const TwoFields & f = ReturnMyFields(v);
 
S

Stefan Ram

=?UTF-8?B?RXJpayBXaWtzdHLDtm0=?= said:
inline TwoFields ReturnMyFields(int myInt) {
TwoFields myReturnStruct; [...]
return myReturnStruct;
const TwoFields & f = ReturnMyFields(v);

How long will the object created with »TwoFields myReturnStruct;« live?

I used to believe that its lifetime would end not later than the
evaluation of the full expression »ReturnMyFields(v)« or even
when the control is leaving the block containing its declaration.
 
E

Erik Wikström

=?UTF-8?B?RXJpayBXaWtzdHLDtm0=?= said:
inline TwoFields ReturnMyFields(int myInt) {
TwoFields myReturnStruct; [...]
return myReturnStruct;
const TwoFields & f = ReturnMyFields(v);

How long will the object created with »TwoFields myReturnStruct;« live?

I used to believe that its lifetime would end not later than the
evaluation of the full expression »ReturnMyFields(v)« or even
when the control is leaving the block containing its declaration.

When you bind a temporary to a const reference the lifetime of the
temporary is extended to last as long as the reference.
 
J

James Kanze

inline TwoFields ReturnMyFields(int myInt) {
TwoFields myReturnStruct; [...]
return myReturnStruct;
const TwoFields & f = ReturnMyFields(v);
How long will the object created with »TwoFields
myReturnStruct;« live?
I used to believe that its lifetime would end not later
than the evaluation of the full expression
»ReturnMyFields(v)« or even when the control is leaving
the block containing its declaration.
[/QUOTE]
When you bind a temporary to a const reference the lifetime of
the temporary is extended to last as long as the reference.

That can easily be misunderstood (and often is). Formally, the
rule is when the initialization expression of a reference is a
temporary, the lifetime of the temporary is extended to
correspond to the lifetime of that reference. Which isn't quite
the same thing.
 
M

mojmir

When you bind a temporary to a const reference the lifetime of the
temporary is extended to last as long as the reference.

i'd just note that sun studio (at least v10) requires -
features=tmplife
option for this to work correctly, otherwise it will destroy the named
temporary at the end of the expression by default.
i spent few days on that one :)

mojmir
 
R

Richard Herring

In message
i'd just note that sun studio (at least v10) requires -
features=tmplife
option for this to work correctly, otherwise it will destroy the named
temporary

What is a "named temporary"?
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,234
Latest member
SkyeWeems

Latest Threads

Top