2

I am currently working my way through C++ Primer Fifth Edition. I have gone through a couple of other C++ books, but they weren't very detailed and were quite complicated.

This book has been helping me a lot with everything that I have missed. I've just hit a wall.

One of the exercises asks me to write a declaration for a function that returns a reference to an array of ten strings, without using trailing return, decltype, or type alias.

I know it only says write a declaration, which I have done, like so:

string (&returnArray()) [10];

I wanted to write a function definition as well, like so:

string (&returnString(int i, string s)) [10]
{
    string s1[10];

    s1[i] = s;

    return s1;
}

In my main function, I have a for loop which passes a string literal through and stores that string inside a pointer to an array of ten strings. It should then output the results to the screen.

The problem I am having is, when I dereference my pointer to an array, once, it will output the address. If I dereference it twice, the program outputs nothing and stops responding.

Here is my main function, I have changed it multiple times, yet can't figure out why it's not outputting properly. I've probably got it all wrong...

int main()
{
    string (*s)[10];

    for(int i = 0; i != 10; ++i)
    {
            s = &returnString(i, "Hello");

            cout << s[i] << endl;
    }

    return 0;
}
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
Zichu
  • 25
  • 2
  • 5
    Nobody does this in the real world (apart from very specific cases). Return a vector of strings instead of this. – Neil Kirk Oct 09 '13 at 13:14
  • As said by Konrad Rudolph in his answer, you should never return a reference to a local variable. You might also be interested in reading [this post](http://stackoverflow.com/questions/4643713/c-returning-reference-to-local-variable). – Cassio Neri Oct 09 '13 at 13:16
  • @Neil Kirk I'd say that returning an `std::array` would be the best choice, since the size is known at compile-time. – Zyx 2000 Oct 09 '13 at 22:10
  • @Zyx2000 Unless performance is an issue, I prefer vectors. A string is basically a vector, so you are only increasing overhead by 10% (rough figures I know) – Neil Kirk Oct 09 '13 at 22:32

3 Answers3

3

Your function returns a reference to a local variable – after the call, it’s a dangling reference. You cannot do that.

You can only return references to storage that goes on existing after the end of the function call.

Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214
2

Returning a reference to a temporary local object invokes undefined behavior.

A short fix is making it static:

string (&returnString(int i, string s)) [10]
{
    static string s1[10];
    ^^^^^^

    s1[i] = s;

    return s1;
}

int main()
{
    string(&s)[10] = returnString(0, "Hello");

    for (int i = 0; i != 10; ++i)
    {
        s[i] = "Hello";
        cout << s[i] << endl;
    }
}
masoud
  • 55,379
  • 16
  • 141
  • 208
  • Thanks a lot. I had to change a bit of the code as well. In the for loop, I kept it the same as before, but changed my output from s[i] to just **s. This now outputs the word "Hello" 10 times. Sometimes I keep thinking I have to just use what has been taught within that chapter, but I should think outside of the box. – Zichu Oct 10 '13 at 09:29
0

Returning pointers/references to local variables is bad, undefined behavior. You can follow your exercise and not forget that constraint, your exercise tells you to do something but it's not necessarily telling you to do it the wrong way, in fact it's a good one that will lead you to pitfalls and hence make you a better programmer once you figure them out.

So what's left given that constraint of not returning addresses to local variables but still addressing the task given? You have the static fix as M M. already mentioned, or you could think you're creating something useful like a function rotate, for example, that accepts an string(&)[10] and returns itself rotated ;-)

Look that, iostream insertion and extraction operators already work like that, returning references to parameters passed by reference.

oblitum
  • 11,380
  • 6
  • 54
  • 120