Introduction
This blog goes over some commonly confusing concepts Reference vs Values. The concepts are slightly differently implemented in different programming languages. The blog attempts to survey or summarize the most basic points of the concepts, and leave the more advance details in "Read more" links.
First, I describes the differences between pointer and references in C++, well, in order to clarify "References" concept in C++. After that, I compared the C++ reference with C# reference.
General concepts of Values and References:
According to wikipedia, in the context of programming, we have the general concepts for all languages:
- a value is the representation of some entity that can be manipulated by a program. A value is a fully self-describing piece of data. Equal values are indistinguishable at program runtime
- a reference is a value that enables a program to indirectly access a particular data
- Reference types are represented as a reference to another value, which may itself be either a value or reference type
Implementation and concepts of the two are slightly different and discussed in below sections.
According to the page by University of Washington,
- Pass by value: making a copy of the actual parameter's value that is passed in, a copy of the contents of the actual parameter and put into the function.
- Pass by reference: a copy of the address of the actual parameter is given to the function. Thus the function has the same access to the object outside function, and changes to object inside the called function also affect the object outside the called function.
References vs Pointers in C++
According to GeeksforGeeks, we distinguish References vs Pointers in C++
| References | Pointers | |
| Definition | A reference variable is an alias, that is, another name for an already existing variable. A reference can be thought of as a constant pointer. | a variable that holds the memory address of another variable |
| Content inside | Stores the address of an object that is located elsewhere in memory heap.(1) | Stores the address of an object that is located elsewhere in memory heap. |
| Memory location | whereas a reference shares the same memory address with the original variable in the heap but also takes up some space on the stack when it is passed to function. | A pointer has its own memory address and size on the stack. (2) |
| Initialization | must be assigned a value when initialized in a single step (3) | can be initialized and assigned value later. (4) |
| Immutability | reference cannot be re-assigned. | can be reassigned to point to another object if it is not declared const. |
| Null | cannot be null. | can be null. Safe code should at least assign nullptr to a pointer. |
| Arithmetic operation | cannot do. | can do. can even have double pointer. |
| Array decay/ Array passing to function | You can pass a reference to array to a function, but it behaves the same as passing an array by value to the function (5) | If array is passed to a function by value , it is the pointer to the first element of the array is passed to the function. Thus this is the similar to passed by pointer. Value changed to the array inside the function is also changed in the calling function. (6) |
Notes:
(1) The address of a reference is the address of the item that it referes to:
#include <iostream>
using namespace std;
int main()
{
int a= 5;
int &ref = a;
cout<<"address of a ="<<&a<<std::endl;
cout<<"address of ref="<<&ref<<std::endl;
return 0;
}
/* ouput:
address of a =0x7fff95acd1fc
address of ref=0x7fff95acd1fc
*/
(2) The pointer itself is on a stack. The memory location it points to is on the heap. Thus when we initialize the pointer with pointer = new something(), we allocate a memory in the heap for the object of something that the pointer points to. The pointer itself is still on a stack. We run delete pointer, we actually deallocate the memory location in the heap that the pointer points to.
(3) Syntax for initializing a reference in C++ is similar to below:
int a = 5 ;
int &ref = a; // initialization and assignment must be done in 1 step
cout<<ref; // output: 5. There is no need to dereference the ref
(4) Syntax for initializing, assignment, aritmetic operations of pointers in C++ is similar to below:
int a = 5 ;
int *pointer = &a; // assign value to pointer to the address of a
cout<<*pointer<<endl; // must dereference pointer to access the value in the heap. Output 5
int array[3] = {1,2,3};
int *ptr = array;
cout<<*(++ptr)<<endl; // can perform arithmetic on pointer (++). Output: 2
(5) and (6) A sample program that illustrated the changes in values of an array when it is passed into the function:
#include <iostream>
using namespace std;
void passByPointer (int array []){
array[1] = 5;
array[2] = 6;
}
int main()
{
int array[3] = {1,2,3};
passByPointer(array);
cout<<array[1]<<" "<<array[2]<<endl; // the values in the array is changed in same way
// that a pointer is passed to the function.
// Output: 5 6
return 0;
}
In other words, the compiler treats void foo(int a[]) the same as void foo(int a*) and foo(int (&a)a[])
Read more
- References vs Pointers in C++: https://www.geeksforgeeks.org/pointers-vs-references-cpp/
- Explaining locations of local variables, parameters, pointer in stack, and values in heap: https://hackthedeveloper.com/memory-layout-c-program/
- There is no differences between passing an array by value or passing a pointer to array to a function. https://stackoverflow.com/questions/5573310/difference-between-passing-array-and-array-pointer-into-function-in-c
Reference Type in C++ vs C#
In C#, there are 2 types: value types and reference types. Variables of reference types store references to their data (objects), while variables of value types directly contain their data. According to an opinion in Quora, C# reference is closer to pointer in C++.
| C++ | C# | |
| Definition | C++ reference, is an alias for another object | A C# reference, like a C++ pointer, stores the address of an object that is located elsewhere in memory |
| Data Structure | a reference could be alias to an object of any data type. | The following data structures are reference types: class, interface, delegate, record, dynamic, object, string * Note that struct is no reference type.* ref keyword also makes a variable of any data type a reference type. |
| Declaration/Initalization Syntax | C++ reference are declared with & | C# reference variable could be explicitedly declared by keyword ref (1)But for some data structures, the variable is already of reference type. |
| Member access syntax | C++ reference can access their object member that it references to by dot . operator | C# reference can access their object member that it references to by dot . operator |
| Memory location | C++ reference is at the same address of the object the references to. That is in the heap. | C# reference are stored in memory locations separate from the objects that it references to. C# reference is in the stack. (2). |
| Reassignment | No, C++ reference can't be reassigned to another value/object. | Yes, C# reference could be reassigned; that is: it could be re-referenced to another object. |
| Nullable | No, C++ reference can't be null. | C# could be null and should be check null before accessing. |
| Memory saving | Pass by Reference would save memory in C++ as no copy is made as the program doesn't make copy of the parameter and passes to the called function. | Using reference is more costly in C#. Reference types require extra memory allocation and deallocation of the object it refers to on the heap. Deallocation is automatically done by C# garbage collection mechanism. |
| Passing a ref to function parameter | When a reference is passed into the function, pass by reference is done: change to the item inside the called function is also returned to the reference item outside the function. | When a reference type is passed to a function, there is no need to use keyword ref to invoke pass by reference. Change to the arguments inside the called function also effect the items outside the function. (3) |
Notes:
(1) Declaring a variable as a reference to another variable is similar to below:
int num1 = 10;
ref int num2 = ref num1;
(2) In C#, when a reference is created, an object that it refers to is in always the heap, while the reference itself is in the stack.
Note that the value type variable could be in the heap, or in the stack, depending on the situation when it was created. Please refer to this page for more details.
In the following program, Car("Audi", price) is itself an object, placed in the heap, while testCar is the reference, placed in the stack.
public class Car
{
public string manufacturer;
public int price;
public Car(string manufacturer, int price)
{
this.manufacturer = manufacturer;
this.price = price;
}
}
class Program{
static void Main(string[] args)
{
int price = 20000;
Car testCar = new Car("Audi", price);
}
}
The following diagram illustrates a memory status of the above program when it executes Main function, upto creating the reference type testCar and calling Car constructor, but not yet finishing main function.

While this page described well the differences between Reference Types vs Value Types, I disagree with the Memmory Allocation section and would refer to this page that describes more convincingly how reference and values are allocated in memory layout of a C# program.
(3) Class in C# is reference type. The program below illustrates how reference type item could be changed:
- if a reference class is reassigned to another class, change in the later will effect the former. In this case, the change in class2 also effect the class1.

- when class2 is passed into a function as a parameter, a reference
class2is passed by value toMyFunctionClass. Sinceclass2is a reference, it points the objectMyClassin the heap, and a copy of its, from insideMyFunctionClassalso points at the same objectMyClassin the heap. - Thus change to
class2will alter objectMyClassin the heap and thusmyclass2outsideMyFunctionClass.

using System;
namespace MyNameSpace{
public class MyClass {
public int x { get; set; }
public int y { get; set; }
}
public class MyFunctionClass{
public void MyFunction (MyClass myClass) {
myClass.x = 40;
myClass.y = 70;
}
}
public class HelloWorld
{
public static void Main(string[] args)
{
MyClass class1 = new MyClass();
class1.x = 1;
class1.y = 2;
Console.WriteLine($"class1 : x={class1.x} , y={class1.y}");
MyClass class2 = class1; // since class is reference type, change to class2 also effect class1
class2.x = 4;
class2.y = 7;
Console.WriteLine($"class1 : x={class1.x} , y={class1.y}");
MyFunctionClass myFunctClass = new MyFunctionClass();
myFunctClass.MyFunction(class2); // class2 is reference but pass by value: a copy of class2 is made and given to MyFunction
Console.WriteLine($"class1 : x={class1.x} , y={class1.y}");
}
}
}
// Output
// class1 : x=1 , y=2
// class1 : x=4 , y=7
//class1 : x=40 , y=70
(3) Class in C# is reference type (I mentioned it again). When we pass "a class" to a function as a parameter, a reference to the class object is passed by value. Thus, change to the class, a reference to the class object to be exact, from inside the called function will affect the original class from outside the called function:
using System;
public class MyClass {
public int a = 5;
public int b = 6;
}
public class OtherClass {
public void changeMyClass (ref MyClass myclass){
myclass.a = 10;
myclass.b = 100;
}
}
public class HelloWorld
{
public static void Main(string[] args)
{
MyClass myclass = new MyClass();
Console.WriteLine ("MyClass() before: " + myclass.a.ToString() + " " + myclass.b.ToString());
OtherClass other = new OtherClass();
other.changeMyClass (ref myclass);
Console.WriteLine ("MyClass() before: " +myclass.a.ToString() + " " + myclass.b.ToString());
}
}
Read more
- References type vs value types in C#: https://marketsplash.com/tutorials/c-sharp/ref-type-vs-value-type-csharp/
- Stack and Heaps in C# program https://endjin.com/blog/2022/07/understanding-the-stack-and-heap-in-csharp-dotnet
- String and Struct are value types and is/could be immutable https://stackoverflow.com/questions/3751911/why-are-c-sharp-structs-immutable
- Pass by Reference vs Pass by Value in C#: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/method-parameters
References in Java (Kotlin)