It can indeed be a bit confusing. Here's a few tips on how to think of the differences:
In C++ a pointer and a reference is essentially the same thing, in fact in the memory they are represented exactly the same way, i.e. as an address to something. The only difference (besides syntax) is that a pointer can be null, but a reference cannot (well, it can, but is not supposed to be).
A reference in AngelScript is an exact match to the C++ reference. The 'in', 'out', and 'inout' keywords added in the AngelScript syntax tells the AngelScript compiler how the value pointed to by the reference will be used. An 'in' reference is used as an input parameter to the function, i.e. the function will read from the reference but will not update it. An 'out' reference is contrary, the parameter will be updated by the function to return a value to the calling function. To C++ these keywords don't mean anything, but they are very important to AngelScript in order to keep the script from doing things it mustn't do (sandboxing).
An object handle in AngelScript is represented in memory as an ordinary C++ pointer, but the object it points to is a reference counted object. When a C++ function receives a handle from a script in a parameter it is responsible for releasing that reference when it is done with it. Likewise, when a C++ function returns a handle to the script it must make sure to increment the reference count.
If a C++ function takes a parameter as 'const string &' then you will want to register it as 'const string &in'. If the C++ function takes a 'string &' and is really meant to be an output parameter then you want to register it as 'string &out'. If the C++ function takes a 'string &' and uses the parameter both as input argument and output argument, then you will need to implement a wrapper function as it is not allowed to register a value type as 'string &inout' (because it isn't possible to always guarantee the lifetime of the reference in this case).
For reference types, like the array, you will usually use either @ or &. Use @ if it is a valid scenario to have null instead of an object, and & if it is not. If you do not use either of the two, it means that you're passing the object by value, which makes the AngelScript compiler make a copy of the object (which can be hurtful to the performance if the object is very complex).
Here's a pair of articles of interest in the manual:
Understanding datatypes in AngelScript and C++
Understanding object handles
I hope that helps to clarify things a bít.