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…