简体   繁体   中英

How is C++ function's default parameter passed?

Say I have the following code:

#include <iostream>

using namespace std;

int defaultvalue[] = {1,2};
int fun(int * arg = defaultvalue)
{
    arg[0] += 1;
    return arg[0];
}

int main()
{
   cout << fun() << endl;
   cout << fun() << endl;

   return 0;
}

and the result is:

2
3

which make sense because the pointer *arg manipulated the array defaultvalue . However, if I changed the code into:

#include <iostream>

using namespace std;

int defaultvalue[] = {1,2};

int fun(int arg[] = defaultvalue)
{
    arg[0] += 1;
    return arg[0];
}

int main()
{
   cout << fun() << endl;
   cout << fun() << endl;

   return 0;
}

but the result is still:

2
3

Moreover, when I print out the defaultvalue :

cout << defaultvalue[0] <<endl;

It turn out to be 3.

My question is, in the second example, should the function parameter be passed by value, so that change of arg will have no effect on defaultvalue ?

My question is, in the second example, should the function parameter be passed by value, so that change of arg will have no effect on defaultvalue?

No.

It is impossible to pass an array by value (thanks a lot, C!) so, as a "compromise" (read: design failure), int[] in a function parameter list actually means int* . So your two programs are identical. Even writing int[5] or int[24] or int[999] would actually mean int* . Ridiculous, isn't it?!

In C++ we prefer to use std::array for arrays: it's an array wrapper class, which has proper object semantics, including being copyable. You can pass those into a function by value just fine.

Indeed, std::array was primarily introduced for the very purpose of making these silly and surprising native array semantics obsolete.

When we declare a function like this

int func(int* arg);

or this

int (func(int arg[])

They're technically the same. It's a matter of expressiveness. In the first case, it's suggested by the API author that the function should receive a pointer to a single value; whereas in the second case, it suggests that it wants an array (of some unspecified length, possibly ending in nullptr , for instance).

You could've also written

int (func(int arg[3])

which would again be technically identical, only it would hint to the API user that they're supposed to pass in an int array of at least 3 elements. The compiler doesn't enforce any of these added modifiers in these cases.

If you wanted to copy the array into the function (in a non-hacked way), you would first create a copy of it in the calling code, and then pass that one onwards. Or, as a better alternative, use std::array (as suggested by @LightnessRacesinOrbit).

As others have explained, when you put int arg[] as a function parameter, whatever is inside those brackets doesn't really matter (you could even do int arg[5234234] and it would still work] since it won't change the fact that it's still just a plain int * pointer.

If you really want to make sure a function takes an array[] , its best to pass it like

template<size_t size>
void func (const int (&in_arr)[size])
{
    int modifyme_arr[100];
    memcpy(modifyme_arr, in_arr, size);

    //now you can work on your local copied array
}

int arr[100];
func(arr);

or if you want 100 elements exactly

    void func (const int (&arr)[100])
    {

    }

    func(arr);

These are the proper ways to pass a simple array, because it will give you the guaranty that what you are getting is an array, and not just a random int * pointer, which the function doesn't know the size of. Of course you can pass a "count" value, but what if you make a mistake and it's not the right one? then you get buffer overflow.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM