Value Semantics vs. Reference Semantics Value vs. Reference Semantics Values/Refs
C++ Terminology
Value Semantics | Reference Semantics |
---|---|
focuses on values | focuses on object identities |
Value Variables | Reference Variables |
|
|
Value Members | Reference Members |
|
|
Deep Copying | Shallow Copying |
|
|
Deep Assignment | Shallow Assignment |
|
|
Equality-Based Comparison | Identity-Based Comparison |
|
|
struct Point2d { int x; int y; }; Point2d a {1,2}; Point2d b = a; // deep copy cout <<"a: "<< a.x <<' '<< a.y <<" " <<"b: "<< b.x <<' '<< b.y <<'\n'; if (a == b) cout << "equal\n";
a.x = 8; cout <<"a: "<< a.x <<' '<< a.y <<" " <<"b: "<< b.x <<' '<< b.y <<'\n'; if (a != b) cout << "different\n";
a: 1 2 b: 1 2 equal
a: 8 2 b: 1 2 different
class Point2d: def __init__ (self, x, y): self.x = x self.y = y a = Point2d(1,2) b = a // shallow copy print("a:", a.x, a.y, " b:", b.x, b.y)
a.x = 8; print("a:", a.x, a.y, " b:", b.x, b.y) if a == b: print("equal") if a is b: print("identical")
a: 1 2 b: 1 2
a: 8 2 b: 8 2 equal identical
Most programming languages use value semantics for fundamental types (also called
primitivesin some languages). So there is no difference between, e.g., C++ and Python/Java/C#/Swift in that regard.
C++ (value semantics)
int a = 2; int b = a; cout <<"a: "<< a <<" b: "<< b <<'\n';
a = 8; cout <<"a: "<< a <<" b: "<< b <<'\n';
a: 2 b: 2
a: 8 b: 2
Python (value semantics)
a = 2 b = a print("a:",a," b:",b)
a = 8 print("a:",a," b:",b)
a: 2 b: 2
a: 8 b: 2
auto print = [](std::string_view s, auto const& v){ cout << s << ": "; for (auto x : v) cout << x << ' '; cout << '\n'; };
vector<int> a {1,2,3,4}; vector<int> b = a; // deep copy print("a", a); print("b", b); if (a == b) cout << "equal\n";
a[0] = 9; print("a", a); print("b", b); if (a != b) cout << "different\n";
a: 1 2 3 4 b: 1 2 3 4 equal
a: 9 2 3 4 b: 1 2 3 4
different
a = [1,2,3,4] b = a // shallow copy print("a:", a, " b:", b)
a[0] = 9; print("a:", a, " b:", b) if a == b: print("equal") if a is b: print("identical")
a: [1,2,3,4] b: [1,2,3,4]
a: [9,2,3,4] b: [9,2,3,4] equal identical
C++, C
- default: value semantics for fundamental types and user-defined types
- reference semantics for C-arrays and C-strings – which is one reason to avoid them in C++
- compiler auto-generates deep copying and deep assignment operations for
struct
/class
- as of C++20 user can request compiler to also auto-generate deep comparisons
- optional reference semantics (through references/pointers) for all types
Rust
- default: value semantics for all types, but only fundamental types are copied and user-defined types are moved
- user defined types can be made copyable by deriving the
Copy
trait and implementingClone
- optional reference semantics (through references/pointers) for all types
Python
- default: value semantics for
primitive
types and reference semantics for lists, dictionaries andclass
types - no first-class support for user-defined value types
- if needed, deep copying and deep comparison can be done by manually implementing special methods (
__deepcopy__
,__eq__
, …)
Java
- default: value semantics for
primitive
types and reference semantics forclass
types - reference semantics for primitive types can be achieved by boxing it inside a class
- no first-class support for user-defined value types
- if needed, deep copying and deep comparison can be done by manually implementing special methods (
clone
,equals
, …)
Javascript
- default: value semantics for
primitive
types and reference semantics forobject
types - no first-class support for user-defined value types
- deep copying usually done by either converting object to JSON string and parsing it back into a new object or with a library like
rfdc
orlodash
Comments…