In .NET, there are two categories of types, reference types and value types.
Structs are value types and classes are reference types.
The general difference is that a reference type lives on the heap, and a value type lives inline, that is, wherever it is your variable or field is defined.
A variable containing a value type contains the entire value type value. For a struct, that means that the variable contains the entire struct, with all its fields.
A variable containing a reference type contains a pointer, or a reference to somewhere else in memory where the actual value resides.
This has one benefit, to begin with:
- value types always contains a value
- reference types can contain a null-reference, meaning that they don't refer to anything at all at the moment
Internally, reference types are implemented as pointers, and knowing that, and knowing how variable assignment works, there are other behavioral patterns:
- copying the contents of a value type variable into another variable, copies the entire contents into the new variable, making the two distinct. In other words, after the copy, changes to one won't affect the other
- copying the contents of a reference type variable into another variable, copies the reference, which means you now have two references to the same somewhere else storage of the actual data. In other words, after the copy, changing the data in one reference will appear to affect the other as well, but only because you're really just looking at the same data both places
When you declare variables or fields, here's how the two types differ:
- variable: value type lives on the stack, reference type lives on the stack as a pointer to somewhere in heap memory where the actual memory lives (though note Eric Lipperts article series: The Stack Is An Implementation Detail.)
- class/struct-field: value type lives completely inside the type, reference type lives inside the type as a pointer to somewhere in heap memory where the actual memory lives.
The differences between a class
and a struct
in C++ is:
struct
members and base classes/structs are public
by default.
class
members and base classes/struts are private
by default.
Both classes and structs can have a mixture of public
, protected
and private
members, can use inheritance and can have member functions.
I would recommend you:
- use
struct
for plain-old-data structures without any class-like features;
- use
class
when you make use of features such as private
or protected
members, non-default constructors and operators, etc.
Best Solution
According to the very popular WWDC 2015 talk Protocol Oriented Programming in Swift (video, transcript), Swift provides a number of features that make structs better than classes in many circumstances.
Structs are preferable if they are relatively small and copiable because copying is way safer than having multiple references to the same instance as happens with classes. This is especially important when passing around a variable to many classes and/or in a multithreaded environment. If you can always send a copy of your variable to other places, you never have to worry about that other place changing the value of your variable underneath you.
With Structs, there is much less need to worry about memory leaks or multiple threads racing to access/modify a single instance of a variable. (For the more technically minded, the exception to that is when capturing a struct inside a closure because then it is actually capturing a reference to the instance unless you explicitly mark it to be copied).
Classes can also become bloated because a class can only inherit from a single superclass. That encourages us to create huge superclasses that encompass many different abilities that are only loosely related. Using protocols, especially with protocol extensions where you can provide implementations to protocols, allows you to eliminate the need for classes to achieve this sort of behavior.
The talk lays out these scenarios where classes are preferred:
It implies that structs should be the default and classes should be a fallback.
On the other hand, The Swift Programming Language documentation is somewhat contradictory:
Here it is claiming that we should default to using classes and use structures only in specific circumstances. Ultimately, you need to understand the real world implication of value types vs. reference types and then you can make an informed decision about when to use structs or classes. Also, keep in mind that these concepts are always evolving and The Swift Programming Language documentation was written before the Protocol Oriented Programming talk was given.