Value Semantics vs. Reference Semantics Value vs. Reference Semantics Values/Refs

    object = set of bits interpreted according to a type
    focuses on values focuses on object identities
    Value Variables Reference Variables
    • refer to objects itself, i.e., one specific memory location
    • exactly one value variable per object
    • lifetimes of variable and associated object are identical
    • may refer to any memory location that holds a type-compatible object
    • many reference variables per object possible
    • lifetimes of variable and referenced object are independent
    Value Members Reference Members
    • are usually stored as part of the containing object
    • refer to objects with the same lifetime as the containing object
    • refer to separately stored objects
    • have independent lifetimes from referenced objects
    Deep Copying Shallow Copying
    • produces a new, independent object; object (member) values are copied
    • produces a new reference to the same object
    Deep Assignment Shallow Assignment
    • makes value of target object equal to that of the source object
    • is either done by (recursively) copy-assigning members or alternatively by transferring ownership, i.e., (recursively) moving the source's value into the target
    • target variable is redirected to refer to the same object as the source variable
    Equality-Based Comparison Identity-Based Comparison
    • objects are equal, if their (member) values are equal
    • objects are identical, if their memory addresses are equal

    Example: Classes Classes

    C++ (value semantics) C++

    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

    Python (reference semantics) Python

    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

    Example: Fundamental Types Fundamentals

    Most programming languages use value semantics for fundamental types (also called primitives in some languages). So there is no difference between, e.g., C++ and Python/Java/C#/Swift in that regard.

    Example: Lists Lists

    C++ (value semantics) C++

    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

    Python (reference semantics) Python

    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

    Language Situation Languages

    • 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
    • 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 implementing Clone
    • optional reference semantics (through references/pointers) for all types
    • default: value semantics for primitive types and reference semantics for lists, dictionaries and class 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__, …)
    • default: value semantics for primitive types and reference semantics for class 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, …)
    • default: value semantics for primitive types and reference semantics for object 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 or lodash