Search code examples
c++arraysfunctionpointersstdstring

How this std::string pointer turns into array?


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

Solution

  • 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);