Your analogy to C++ is incorrect. Passing reference objects* in C# is similar to passing objects by pointer in C++, with the exception that C# does not require an asterisk to dereference these pointers.
Passing by reference in C# would be similar to passing a pointer by reference in C++: in addition to using that pointer inside your function, you would also be able to assign a new value to it, thus changing the value of the pointer in the caller.
Here is a short illustration:
void One(List<int> list) {
// Reassignment of the list is local to method One
list = new List<int> {1, 2, 3};
}
void Two(ref List<int> list) {
// Reassignment of the list is visible in the caller
list = new List<int> {1, 2, 3};
}
...
var demo = new List<int> {5, 6, 7};
One(demo);
// Here the list remains [5, 6, 7]
Two(ref demo);
// Here the list becomes [1, 2, 3]
* As opposed to value objects, such as struct
s and primitives, which are copied.