2

Hi I am having trouble with this code here from a tutorial about returning Arrays from functions

std::string(&func(std::string(&arr)[10]))[10]
{
    return arr;
}

int main()
{
   std::string array[10] = { "efwefwef","wefffj","mfls","hrkr","sgte","ege","ky","retg","sujtre","fl;yiu" };

   std::string* array23 = func(array);
   std::cout << array23[0] << std::endl; // why does this work
   std::cout << array23[1] << std::endl; // why does this work
}

It compiles fine but I am confused as to how std::string* array23 can be used with the index operator.

I initially thought that this was because std::string was an array of characters and you could access them individually with the index operator but this next code works and I can not figure out why.

::std::uintptr_t x = 2453;
::std::uintptr_t* pX = &x;
std::cout << "Var: " << pX[0]; // pX prints 2453
JeJo
  • 30,635
  • 6
  • 49
  • 88
Ayyware
  • 53
  • 5
  • In absence of operator overloading, `a[b]` is equivalent to `*(a+b)`. Also I'm not sure what `func` is for, you could write `std::string *array32 = array;` directly. And if a tutorial uses convoluted declarations like `std::string(&func(std::string(&arr)[10]))[10]` for any purpose other than teaching you how to read them, it's probably not the best tutorial. – HolyBlackCat Aug 29 '20 at 10:25
  • I have no idea what this code does; that declaration is far too complicated for pretty much anyone to read. Use `typedef` to create names for intermediate types and use those. – Pete Becker Aug 29 '20 at 14:54

1 Answers1

2

The plane arrays(c-style) can be decayed to a pointer to the type of the array, and the pointee can be accessed using operator[] (i.e pointer[index]).


The function func returns the reference to an (c-style) array of std::strings with 10 elements in it.

If you write the function clearly with an alias, it would look like:

// alias type: the returned type!
using Type = std::string(&)[10];

Type func(std::string (&arr)[10])
{
    return arr;
}

The std::string(&)[10] array elements can be accessed like normal c-style array via operator[]. So the question is why the code you showed works (i.e. std::string* array23)?

This because of the reason mentioned above. In the case of

std::string* array23 = func(array);

The returned (c-style) array(i.e. from func(array);) is decay to the pointer pointing to the first element of the array.

Meaning

array23[0]

is equivalent to

*(array23 + 0)

and hence it works! The same applies to array23[1] (i.e. equalent to *(array23 + 1)).


If you write the actual type instead there, you need

std::string (&array23)[10] = func(array);
// or
// Type array23 = func(array);
JeJo
  • 30,635
  • 6
  • 49
  • 88
  • 1
    *"func returns the reference to an array ... meaning ... `std::string* array23` ... is equivalent to ... `std::string (&array23)[10]` ... therefore ... `operator[]` ... works"* I feel this is very very misleading. The two are not equivalent. And `[]` working has nothing to do with `func` returning a reference. – HolyBlackCat Aug 29 '20 at 10:36
  • 1
    @HolyBlackCat Yes, realized after wrote the answer. Updated the answer as per. Thanks for pointing out. It should be clear now. – JeJo Aug 29 '20 at 10:43