Returning a struct

Suppose you have a function that returns a struct, but doesn't take a struct as a parameter.  Is there a way to return all the struct values?

Something like:

typedef struct {
   char* word;
   int len;
}thing;

thing& func1(char* str)
{
   return { str, strlen(str); }  
}

The above code doesn't work, of course, but hopefully it shows what I'm trying to do.  func1 is a function of type thing, which is a struct - how can I return both values of struct from the function, and it is correct to pass a struct as a reference?
chsalviaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

AlexFMCommented:
You can return local variable by value:

thing func1(char* str)
{
    thing s;
    s.word = str;
    s.len = strlen(str);
    return s;
}

You can return pointer to allocated structure, client is responsible to release it:

thing* func1(char* str)
{
    thing* p = new thing();
    p->word = str;
    p->len = strlen(str);
    return p;
}

You cannot return reference to local variable which is destroyed when function exits. You can retun reference to global variable or class member, bt I don't think that this is what you want.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
leisnerCommented:
AlexFM,

In this example:
thing func1(char* str)
{
    thing s;
    s.word = str;
    s.len = strlen(str);
    return s;
}
do you mean can or can't?   thing is on the stack, so it goes away when the
function goes out of scope -- which is a bug.

If you want to return multiple elements, you create temporary structures, or pass by reference....

Another way is for the caller to allocate the structure, pass down a pointer to it, and maybe the
calling function return status?

For example:

bool func1(thing *pthing, char *string)
{
    if(NULL == pthing || NULL == string)
        return false;
   pthing->word = strdup(string); // do you want the string or a copy to it?
   pthing->len = strlen(string) + 1; // add the NULL terminate?
   return true;
}

If you want  the return value to be the structure, you can use static instead of auto inside the
function -- but only one copy of the data is valid at one time.

0
AlexFMCommented:
My first sample is OK, it doesn't return reference. It returns structure by value - this means, caller gets temporary structure instance which is assigned to it's variable:

thing t;
t = func1("bla");
0
Cloud Class® Course: MCSA MCSE Windows Server 2012

This course teaches how to install and configure Windows Server 2012 R2.  It is the first step on your path to becoming a Microsoft Certified Solutions Expert (MCSE).

leisnerCommented:
Yep, AlexPM, you're right.

But one caveat of that style of function calls -- you make an extra copy of the structure.
In this case the cost is minimal, but if you start  call to func1 repeatedly and thing is large, it gets expensive....

0
rajeev_devinCommented:
>> But one caveat of that style of function calls -- you make an extra copy of the structure.
In that case don't return it. Do something like this

void func1(char* str, thing& t)
{
    t.word = str;
    t.len = strlen(str);
    return s;
}
0
cupCommented:
I've had lots of problems with this particular style of programming

thing func1(char* str)
{
    thing s;
    s.word = str;
    s.len = strlen(str);
    return s;
}

especially in a multi-tasking environment.  I've seen it in a few books and some people swear by it but I wouldn't recommend returning anything other than a basic type or a pointer.  I've had no end of crashes when there are shallow copies and destructors delete pointers to arrays.  If you must use this style, do it this way

thing func1(char* str)
{
    static thing s;
    s.word = str;
    s.len = strlen(str);
    return s;
}

That way, you know the stack will not be wiped and no destructor will be called.  The only problem is that the result must be stored straight away and it is not thread safe.
0
itsmeandnobodyelseCommented:
>>>> thing& func1(char* str) {  return { str, strlen(str); }   }

You could do the following:

thing& func(char* str)
{
     static thing s = { 0 };   // init
     thing t  = { str, strlen(str) };
     return s = t;
}

Here you return the static variable by reference (what isn't thread-safe as cup already told).

>>>> return s = t;

That invokes the (automatically generated) copy constructor of struct thing. However, it doesn't work in C but only in C++ cause there is no copy constructor in C. To make that clear I would change the definition of the struct to

struct thing
{
     char* psz;
     int     len;
};

BTW, I would not use the name 'word' for a string variable cause 'word' means a 16-bit integer.

Regards, Alex


0
itsmeandnobodyelseCommented:
>>>> That invokes the (automatically generated) copy constructor of struct thing.

It is the assignment operator that is invoked, *not* the copy constructor.
0
itsmeandnobodyelseCommented:
>>>> but if you start  call to func1 repeatedly and thing is large, it gets expensive....

Repeatedly means "millions of repetitions" before you actually could measure a difference.  The "expensive" argument came from times of 16-bit code where the stack was limited to some k bytes. If 'thing' is a structure where you have a few instances only, it doesn't matter - regarding effiency - whether it is passed by reference or by value. Actually, all modern container classes store by value (means they make copies from elements that were passed by value).

Regards, Alex

0
itsmeandnobodyelseCommented:
>>>> Accept: AlexFM {http:#16293571}

Yes, that's a good decision.

Regards
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Editors IDEs

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.