If your function parameter is (int *, int), when you call create(a, len), the system will push the value of the starting address of array A (note: this value is NULL at this time, but why this value does not affect the following explanation) onto the parameter stack. Then the program jumps to the create function and starts execution.
At this point, the system creates a temporary variable of type int *, which we might as well call ap. Then, the system finds the pushed parameter value (that is, the null value mentioned above) from the parameter stack and assigns it to the ap.
That is, the pointer ap can be regarded as having the same value as the passed-in pointer, that is, the temporary variable ap points to the beginning of the passed-in array (actually ap = NULL).
After that, the system executes ap = new int[n] statement, applies for a new area in memory, and assigns its starting address to ap again. After this operation, the value of the original pointer A has not changed! Only the value of the temporary pointer variable ap is changed!
After that, the system exits the create function and the temporary variable ap is destroyed! And the value of the original pointer variable a is still NULL!
And you change the parameter table to (int * &;; Int), which makes use of the syntax sugar in C++: reference. After the ampersand is added, the reference mechanism will automatically address the incoming parameters, thus realizing the address call.
In this way, when you call create(a, len), the system will push the pointer address of array A into the parameter stack. After entering the create function, the system will implicitly create a temporary variable (called app) to make its value equal to the pushed address. The reference mechanism implicitly completes the assignment operation of *(app) = new int[n] when executing the statement ap = new int[n]. Because app is a pointer to array A, it actually changes the value of pointer A to point to a meaningful memory space.