4

What are the relationships between these pairs of concepts:

For the first pair of concepts, it seems to me that an object of value type is an element (data or procedure), and an object of reference type is the location (absolute or relative) of an element.

Questions:

  • Is an object of value type a value object?
  • Is an object of reference type a reference object?
  • Does an object of value type have value semantics?
  • Does an object of reference type reference semantics?
Theraot
  • 8,921
  • 2
  • 25
  • 35
Géry Ogam
  • 602
  • 3
  • 13

4 Answers4

10

TL;DR

Note. — The meaning of "value semantics" in the context of programming has drifted, as evidenced by the definitions provided in the appendix. What follows is my attempt to make sense of it all.

  • Value semantics is instance independence.
  • Value-semantic types are types with value semantics.
  • Reference semantics is instance interdependence.
  • Reference-semantic types are types with reference semantics.
  • Value type variables hold instances.
  • Reference type variables hold references to instances.
  • Objects are instances of classes.
  • Value objects have value based equality.
  • Value objects should have value semantics.
  • Value objects can be instances of either value types or reference types.
  • Reference objects have identity based equality.
  • Reference objects can be instances of either value types or reference types.
  • Entities are reference objects that have value.
  • Services are reference objects that do not have value.
  • Value semantics can be archived by:
    • Complete copy. Which can be archived by:
      • Shallow copy of value types without reference type fields.
      • Deep copy.
    • Deep copy of mutable fields and shallow copy of immutable fields.
    • Immutable types.
    • Copy-on-write implementation.
  • Reference semantics is archived by… not having value semantics.

Spaces in Memory

Information is stored in spaces in memory where they can be reused. There three spaces in memory:

  • Stack (e.g. arguments, local variables).
  • Heap (e.g. globals, static fields).
  • Relative (e.g. array elements, instance fields).

Of each kind, there can be multiple spaces in memory. For example, multiple arguments. Each a space in memory.

A language/runtime/platform may or may not have any of these. For example, some do not have a stack. Some do not have arrays or composite types. And some do not have a heap. However, they will all have at least heap or stack.

We will not be talking about named constants, literals, immediate values, or the distinction between l-values and r-values.


Variables

In most languages we give names to spaces in memory. This makes it easier to use them. We call these named spaces in memory “variables”.

Going forward, we will refer to the information stored in the space in memory named by a variable as the contents of the variable.

It is also worth noting that the names of the variables may or may not exist in runtime (e.g. reflection), also if they do, their static type information may or may not exist in runtime (e.g. type erasure).

Furthermore, the position in memory of named variable may change.

Note. — What I call here contents, other authors call value. I'm not calling it value, because I'm using Lakos' definition of value. However, I would agree that the contents of a variable is a value. A physical value. While the value that Lakos' talks about is a platonic logic value.


Types and Instances

A type is a set of memory layout. We will refer to each of each of the possible memory layout of a given type that actually exist in memory as instances. Instances may overlap in memory.

These memory layouts will define the contents of the variable that hold said instances. See “Value Types and Reference Types” below.


Variables and Types

In a dynamically typed language, the contents of the variables can be of any type.

On the other hand, in statically typed languages, the variables have a type, and this type specifies the possible contents of the variable.

Note. — Some statically typed language support typing a variable as dynamic. That is, the type of the variable is “look into the contents of the variable to figure out the type”.


Primitive Types and Composite Types

Composite types are types constructed out of other types. Which is not true for primitive types.

Do not confuse primitive types with build-in types. That is the set of types provided by a languages. As currently plenty of languages provide composite types. Instead primitive types are indivisible within the constraints of the language.


Equality

Considering the instances of a type, we may or may not care about a concept of equality for these instances. That is, equality may or may not be part of the specification/requirements for the type.

We only care about equality, when the type has a concept of “value”.


Values

For types that have a concept of value, the value is derived from the contents of the instances. Or rather, I should say, that the contents represent the value.

However, the contents is not the value. I mean, the equality of the instances does not imply equal representation in memory. This is because there could be multiple representations in memory for the same value. Consider, for example, that in some types there are multiple ways to represent a value in memory, and thus would require canonization/normalization (e.g. strings, date, decimal floating point numbers).

This is also how we can say that values stored in different types have the same value, i.e. are equal (e.g. 5 stored in a short integer vs 5 stored in a long integer).


When dealing with composite types, we would talk about salient attributes.

From the book Large-Scale C++ Volume I: Process and Architecture by John S. Lakos:

A salient attribute of a value-semantic type is one of its (typically observable) attributes that contributes to the overall value of the object itself.

Will get to “value-semantic type”.

Only salient attributes are considered part of the value of a type, and which attributes are salient is decided by the specification/requirements for that type, not by the representation in memory.


References

References are variables such that their contents refers to an instance, instead of being an instance. That is, the contents will have a position in memory where an instance is found, instead of containing the instance directly.

What I define above would be pointers in C++. We are not talking about the C++ distinction of pointers and references.

In some platforms there is a garbage collector that may move instances around. When this happens, the garbage collector also has to update the references to them.


Due to composition, we may have instances that have references.


Copy and Move

Since each variable has a space in memory, when we assign a variable to another (assuming their types are compatible) we need to copy the contents. See “Types of Copy” below.

If the types of the variables are not compatible. A conversion is necessary. One special case is when assigning to a reference.

In some cases, we know that a variable will cease to exist. For example, a local variable when returning from a subroutine goes out of scope. If we are returning the local variable, and assigning the returned value to another variable, the compiler may opt to not copy it, but move it instead. Moving here means changing the space in memory named by the variable.

Since move happens only when a variable is ceasing to exist. We do not have to worry about move.


Pass by Reference and Pass by Value

A parameter of a subroutine is a variable. When we call the subroutine, the parameters are assigned. If the parameters are types are references, then we are passing instances by references. Otherwise, they are passing by value. And yes, that is a copy.


Types of Copy

A shallow copy limits itself to copying the contents of a variable. On the other hand, a deep copy would follow references and copy them too. That is, a deep copy is recursive with respect to references.

Please note that these are not the only options when it comes to copy instances. We will come back to that.


For contents that do not include references, a shallow copy is a complete copy. However, for contents that include references, a deep copy is necessary to get a complete copy.

We will understand as complete copy, a copy of the whole memory layout of an instance. If we do not copy the whole, then it is an incomplete copy. If the memory layout does not have references and exists only in the contents of the variable, then a shallow copy is a complete copy. Otherwise, a shallow copy is an incomplete copy.

A shallow copy is the default.


Note. — A variable contents could be a handle to a resource. It could be an external resources, such as a a handle to a window object or a key to a row in a database table. It could also be an internal resource such as an index to an array (See Entity-Component-System). These are not references as defined above, however they can be considered as such (we could say a pointer is a physical reference, while a handle is a logical reference). If the referenced resources are not copied, they may provide a means for instances to affect each other. See "Rule of Three" below. You may also be interested in RAII. My personal opinion we should not try to archive value semantics with that include handles to external resources, and if we were to, it would require to copy those resources too.


Value Types and Reference Types

We find in the C# language reference:

A variable of a value type contains an instance of the type. This differs from a variable of a reference type, which contains a reference to an instance of the type.

Reference types are types such that variables of that type are references to the instance. That memory layout for reference types defines that the variables hold a reference to the instance.

In C++, only pointers and references are reference types. However, we find plenty of reference types in other languages. For example, Java and .NET classes are reference types. C# structs, by the way, are value types.

On the other hand, value types are types such that variables of that type are not references. In other words, the contents of the variable is the instance.

Do not confuse value types and reference types with value-semantic types and reference-semantic types. Also do not confuse value types with primitive types.


Now, since variables of reference types are references. And a shallow copy is the default. The assignment of reference types results in an incomplete copy… unless the default is overridden.

For value types, the assignment results in a complete copy, if and only, they are not composite types that include references. See also Can structs contain fields of reference types (C#).


Value-Semantic Types and Reference-Semantic Types

A value-semantic type is a type such that copy provides instance independence. That is, the result of the copy should not be usable to mutate the original. Emphasis on copy. This is not about making a reference.

This matches Alexis Gallagher’s Mutation game.

There are two simple ways to accomplish this:

  • Providing a complete copy. As we saw earlier, we can have a complete copy with a value type that includes no reference type fields, or overriding the default copy with a deep copy.
  • Make the type immutable. With an immutable type, a shallow copy will provide instance independence regardless of whatever or not the instance includes references… The reason is that you cannot mutate the original anyway. Which also means that it is OK for immutable instances to share memory.

However, in general, you must provide a copy that copies every part of the instance which is not immutable. If the type is immutable, then shallow copy is sufficient. If the type has no immutable parts (and it is a reference type or a value type which includes references) then you must provide a deep copy. If some parts are immutable and some are not, then you can archive value semantics by doing a deep copy of the mutable parts (and shallow copy of the immutable parts, sharing them). Which, by the way, is neither a shallow copy nor a deep copy, but a mixture.

Note. — Bjarne Stroustrup only considers deep and shallow copy when defining value semantics in Programming: Principles and Practice Using C++.

If we have a reference type, which only contains a field of an immutable reference type. Then it is sufficient to copy that reference. There is no need to copy the immutable instance. Then, when implement mutation operations by swapping that reference with a new one. This is copy-on-write.


Value Objects

From the book Domain-Driven Design: Tackling Complexity in the Heart of Software by Eric Evans (who coined the term “value object”):

Does an object represent something with continuity and identity—something that is tracked through different states or even across different implementations? Or is it an attribute that describes the state of something else? This is the basic distinction between an ENTITY and a VALUE OBJECT.

Evans also had the concern of value semantics:

We don’t care which instance we have of a VALUE OBJECT. This lack of constraints gives us design freedom we can use to simplify the design or optimize performance. This involves making choices about copying, sharing, and immutability.


We see the same definition, and the same concern for value semantics echoed by other authors.

From the book Patterns of Enterprise Application Architecture by Martin Fowler et al.:

The key difference between reference and value objects lies in how they deal with equality. A reference object uses identity as the basis for equality […]. A Value Object bases its notion of equality on field values within the class. Thus, two date objects may be the same if their day, month, and year values are the same. […] Most languages have no special facility for value objects. For value objects to work properly in these cases it’s a very good idea to make them immutable—that is, once created none of their fields change. The reason for this is to avoid aliasing bugs. An aliasing bug occurs when two objects share the same value object and one of the owners changes the values in it.

See also Value Object.


It is worth noting that Evans also describes Entities, which are objects that have value, are mutable, and have identity.

Beyond that, Evans also describes Services, which are objects that do not have value and are about behavior. A lot of threading constructs are services. For example, a read-write lock. A read-write lock is not a value.


Note. — I’m saying that value objects do not imply value semantics, only value equality. However, value semantics is a desirable feature of value objects. We can say that value objects without value semantics are poorly designed.


Bonus Chatter

Rule of three

This is particular to C++.

Let us say we want value semantics, and we have a value type that has no reference type fields. For this, the default shallow copy is sufficient.

Now, let us say we add a reference type field to our type. And thus, our shallow copy results in two instances with fields pointing to the same instance of the reference type.

To avoid the shallow copy we need to override the assignment operator, and implementing a deep copy. However, if we are not assigning to an existing variable but initializing a new one, the assignment operator does not get called, but the copy constructor instead (and again, the default is shallow copy). Thus, we need to override the copy constructor too.

We run into a similar problem with the default destructor. It will not follow reference. That is, it will not do a deep destruction. Which would mean we would be leaking the instance of the reference type field. Thus, we also need to override the default destructor.

Thus, we want to override the assignment operator, the copy constructor and the destructor. This is not possible in most languages.

See also Rule of three.


On References and Value Semantics

We should not require the concept of references or pointers to define value semantics. Languages that do not have these concepts can still have value semantics.


There is another concept related to value objects we need to talk about: data transfer objects. DTOs are meant to cross boundaries. They might be going to another process, even to another machine. They may not. When crossing these boundaries references do not work. And thus, DTOs must avoid references.

DTOs should have no behavior, and have value semantics.

DTOs are often confused with value objects. Martin Fowler:

You usually can’t send the domain object itself, because it’s tied in a Web of fine-grained local inter-object references. So you take all the data that the client needs and bundle it in a particular object for the transfer—hence the term Data Transfer Object. (Many people in the enterprise Java community use the term value object for this, but this causes a clash with other meanings of the term Value Object).


Objects

If you go back to the definition of object (according to Grady Booch), you will find that objects have identity (and state and behavior, which could be none). However, we are ignoring this definition, instead we are saying that objects are instances of classes.

Plus, I would argue that the name value object is influence by the fact that Evans was working in Java, and thus could not define custom value types. To reiterate, Value Objects in Java are of reference types.


Thread Safety

Another argument for value semantics is thread safety.

Please note that if we are passing references, even if const references, that could be modified by another thread behind the scenes, we will run into trouble. Thus, any reference must be to an immutable type or a thread safe type.


Your Questions

is an object of value type a value object?

Value objects can be of value types or reference types.


is an object of reference type a reference object?

Instances of reference types would be reference objects, unless they override equality.


does an object of value type have value semantics?

If it does not have reference type fields, or if it overrides the default copy to provide value semantics.


does an object of reference type have reference semantics?

If it is not immutable and does not override the default copy to provide value semantics.


Appendix: Definitions of "Value Semantics", a time line


1998

This template version of List includes a generic iterator and value semantics to store generic data. Value semantics means that List stores instantiated objects, not pointers to objects. During insertion operations, List stores copies of data values instead of storing pointers. Although containers with value semantics allow applications to manage small objects and build-in types easily, many applications cannot tolerate the overhead of copying objects.

– Paul Anderson, Gail Anderson – Navigating C++ and Object-oriented Design


2004

STL containers are value semantic. When a task object is added to an STL container, the task object's allocator and copy constructor are called to clone the original. Similarly, when a task object is removed from an STL container, the task object's deallocator is called to delete the copy. The value semantics may be a performance concern, especially if producers and consumers frequently add tasks to and remove tasks from a queue.

– Ted Yuan – A C++ Producer-Consumer Concurrency Template Library


2004

ValueSemantics for objects-by-value are preserved by copying values between objects. ValueSemantics for objects-by-reference are preserved by using a CopyOnWrite mechanism. I had always thought that the story ended there. Are ValueObjects simply objects that preserve ValueSemantics or is there something more to them?

– PhilGoodwin – Value Objects Can Be Mutable


2014

Types that provide shallow copy (like pointers and references) are said to have pointer semantics or reference semantics (they copy addresses). Types that provide deep copy (like string and vector) are said to have value semantics (they copy the values pointed to). From a user perspective, types with value semantics behave as if no pointers were involved – just values that can be copied. One way of thinking of types with values semantics is that they “work just like integers” as far as copying is concerned.

– Bjarne Stroustrup – Programming: Principles and Practice Using C++


2015

it's (…) possible for a type to be value semantic provided that it keeps one very important property true which is if two objects of the given type have the same value today and we apply in the same salient operation (by salient I mean an operation that is intended to approximate the Platonic type that lives outside of the process that we're using as our model) then after that operation is applied to both objects they will again have the same value or they never did and that is a key property of value semantics.

Another way to say this would be if two objects have the same value then there does not exist a distinguishing sequence of salient operations that will cause them to no longer have the same value.

– John Lakos – An interview with John Lakos


2016

Value semantics amounts to being a guarantee of the independence of the value of variables.

And independence doesn’t mean structural things. What we’re talking about is can one thing affect another. So a type has value semantics if the only way to modify a variable’s value, a variable that has the value semantic type, is through the variable itself. If the only way to modify a variable’s values is through the variable itself, it’s a variable with semantic type.

(…)

The type is value semantic if it’s immune from side effects produced by other things. Not if it’s guaranteed not to perpetrate side effects on other things.

– Alexis Gallagher – Value SEMANTICS (not value types!)

Theraot
  • 8,921
  • 2
  • 25
  • 35
  • 1
    @Maggyero If we define value-semantics as forbidding mutation based on identical instances, that sounds like value-semantics could allow to mutate an instance by mutating a distinct instance of the same type. However that should not be possible either. So, if identical instances cannot be used to mutate and distinct instances cannot be used to mutate... we are back were we began. As alternative, I'm proposing a different definition, this one is based on Gallagher’s mutation game instead of based on what Gallagher’s says. I also expand on what John S. Lakos says. See updated answer. – Theraot Apr 10 '20 at 13:33
  • Yesterday I proposed new definitions in the comments of [Christophe’s answer](https://softwareengineering.stackexchange.com/a/408552/184279) that finally satisfies me. What do you think? (I starts at "Stroustrup’s illustration is indeed excellent.") – Géry Ogam Apr 12 '20 at 13:16
  • About the copy-and-write implementation, [here](https://stackoverflow.com/a/61198935/2326961) is an example in Python using the decorator design pattern. – Géry Ogam Apr 14 '20 at 00:32
  • Thank you for your tremendous effort and your collaboration, I have learnt a lot! You really deserve it. – Géry Ogam Apr 14 '20 at 18:51
  • Let us [continue this discussion in chat](https://chat.stackexchange.com/rooms/106728/discussion-between-theraot-and-maggyero). – Theraot Apr 15 '20 at 02:39
5

These concepts are very closely related and all speak about the same thing.

The more abstract and general is the semantic:

  • value semantic means that only the value , the content of the object, matters. The unique identity of an object is not relevant. In everyday’s life a date has a value semantic: you can copy the value of that date in 10 documents, for you, wherever you’ll find the date, it’s always the same date.
  • reference semantic means on contrary that the value doesn’t tell it all. Each object has a unique identity, and has a history. It’s the same object whatever value it will take. A typical example in everyday’s life is a person. A person can change its name, its address, its job: it’s still the same person.

I used on purpose everyday’s life example that are not related to programming.

Now if you apply this concept to OOP you will get the concept of value and reference objects. Take the example of integer objects. In most of the languages, integers are value objects: if two integer objects have the same value, they are considered equal, even if it’s two different objects. You can also have a reference object: here you don’t care of the value, but only to the object itself. If you change a reference object, the new value is instantly known everywhere where the reference is used. In C++ you have value objects, but you always can make a reference object by using a pointer to an object or a reference.

Finally reference type vs. value type is the specialisation of the semantic by applying it to types. It’s a concept that is only relevant for typed languages. In C# for example a class is a reference type, and a struct is a value type. This means that every object created with the type as the semantic if the type.

Finally, it is worth to mention that value and reference is also relevant in non OOP language in the context of parameter passing.

Christophe
  • 74,672
  • 10
  • 115
  • 187
  • Great answer Christophe, thanks. I am following you (the value/reference separation is based on the definition of *identity*: state/location identity), until "If you change a reference object, the new value is instantly known everywhere where the reference is used." Do you mean changing the *reference* itself, that is to say the location that it holds, or its *target*, that is to say the state that it refers to? – Géry Ogam Apr 08 '20 at 19:47
  • @Maggyero sorry if this was confusing. Indeed there is a difference between changing the reference to the object and changing the content of the object. But truth is that it depends on the relevant language semantics. In java for example, reference objects are accessed via a handle. Whenever you change the content of the object, every use of that object elsewhere accesses via the reference the changed content. But if you have a variable referring to that object, you can assign another reference object to it, changing the reference. – Christophe Apr 08 '20 at 20:16
  • Alright. By definition changing the state of a value object changes its identity, while changing the state (target) of a reference object does not. Now why a lot of people insist that value objects should be immutable, while other do not impose such a restriction? For instance [here](https://wiki.c2.com/?ValueObjectsCanBeMutable). – Géry Ogam Apr 08 '20 at 21:17
  • 1
    @Maggyero it’s because of the apparent contradiction of “changing a value object changes its identity” which is true in regard of the semantics but might not correspond to the reality of the the implementation (because a memory location could be overwritten in the same variable). This is therefore error prone because the change of identity is implicit. – Christophe Apr 08 '20 at 21:43
  • What a sharp and clear answer! Since mutation does not imply rebinding, now I see how mutable value objects could cause some confusion. But what is surprising is that people work with mutable value objects all the time in some languages, and that does not seem to be an issue. For instance in Python, lists are value objects (since `[1, 2, 3] == [1, 2, 3]`) and they are often mutated (`l = [1, 2, 3]; l.append(4)`). – Géry Ogam Apr 08 '20 at 22:26
  • @Maggyero It depends on the dominant paradigm. Mutations create side effects, and side effects are error-prone. In functional programming languages, you generally try to avoid these, so that the result of a function only depends on the input values. But in many OOP languages, non-mutability means reconstructing the object with some values changed. This can imply additional operations for the construction (can be complex and error-prone as well) as well as a performance cost that you cannot always afford. So it all depends on the context and requirements (ok, also on habits ;-). – Christophe Apr 08 '20 at 22:44
  • [Theraot’s answer](https://softwareengineering.stackexchange.com/a/408558/184279) uses the same definition as yours for *value/reference objects*: equality of state/location. However it uses different definitions, based on [Alexis Gallagher’s article](https://academy.realm.io/posts/swift-gallagher-value-semantics/), for *value/reference types*: assignment by value/reference, and for *value/reference semantics*: remote immutability/mutability. What is your opinion on these? – Géry Ogam Apr 09 '20 at 12:42
  • @Christophe, regarding side effects, would you say that the essence of what functional languages do in this respect, is force you to be explicit about certain temporal aspects of a program? That is, it forces you to either be explicit about the use of intermediary values, which have to be given separate names or identifiers, or else to use standard operators (for example, rather than iterating over an array with a hand-rolled loop to calculate a total, you apply a reduction operator to an array). It's basically modern-day structured programming. – Steve Apr 09 '20 at 14:18
  • @Steve thank you for this interesting idea. As a lambda-calculus enthusiast I would not downgrade functional programming with higher order functions to structured programming. It's really different paradigms. And I avoid any judgement: I think it is really the nature of the problem that should drive our choice of the tools: hammers are in general bad with screws and screwdrivers with nails ;-) – Christophe Apr 09 '20 at 14:37
  • @Maggyero I think that value/reference types are a specialisation of the value/reference semantic that is specific to some programming languages. I agree on the point about assignment. I do not agree however about reducing to mutability/immutability: IMHO this is a very specific view at value/reference semantic. The key to the value/reference semantic is how you define identity. If two clones can be viewed as identical it's value semantic. If I can mutate one of the clone is another story (immutable means you'll need another clone, mutable means that you're allowed to replace the clone) – Christophe Apr 09 '20 at 14:56
  • @Christophe, I use "structured programming" as superlative praise. A set of approaches, now universally implemented, accepted, and understood, and which are the default resort for any programmer. – Steve Apr 09 '20 at 16:05
  • @Steve oh! Thanks for the clarification. With this meaning I can fully agree ;-) – Christophe Apr 09 '20 at 16:17
  • "I think that value/reference types are a specialisation of the value/reference semantic that is specific to some programming languages. I agree on the point about assignment." What is the point of overloading assignment? Overloading equality is not enough to guarantee value/reference semantics? – Géry Ogam Apr 09 '20 at 16:33
  • @Maggyero I was referring to the point about value/reference type and assignment by value/reference. Did you mean overloading or overriding? and in the context of semantics or of types? – Christophe Apr 09 '20 at 18:23
  • "Did you mean overloading or overriding?" Overriding sorry. "and in the context of semantics or of types?" In both contexts. Do we need only equality of state/location or also assignment by value/reference? – Géry Ogam Apr 09 '20 at 18:49
  • [Phil Goodwin said](https://wiki.c2.com/?ValueObject) we need both: "If the definition of value object is an object whose identity is defined by its state rather than by its address, I'm inclined to think that they are defined in C++ as objects that override the copy constructor, assignment and comparison operators to assign and compare state between two objects. Overriding the assignment operator is key and means that in C++ ValueObjectsCanBeMutable and usually are. The aliasing problems addressed in ValueObjectsShouldBeImmutable are generally taken care of by using pass-by-value semantics." – Géry Ogam Apr 09 '20 at 18:50
  • But I don’t know if it is true and why, if it is true. – Géry Ogam Apr 09 '20 at 18:51
  • @Maggyero, I'd say that is a pretty concise explanation by Goodwin, assuming you understand what he means, and all the significance of "identity being defined by state rather than address". – Steve Apr 09 '20 at 19:45
  • @Maggyero the reasons to override an assignment operator are independent of value vs. reference kind. Example: in C++ you could have an object with value semantic in a value type, that caches some data for the purpose of optimizing some behaviors. The semantic can still be completely value based, and only compare/assign the relevant data components, and recalculate (or initialize) on the flow the cached data. In the same scenario, you could also define some objects `const` (immutable), but sill have some `mutable` members (the cached ones). – Christophe Apr 09 '20 at 23:12
  • On [this page](https://wiki.c2.com/?ValueSemantics) they give the *assignment definition*, but it seems equivalent to the *equality definition*, meaning you should have both (value semantics = identity based on state = object that cannot mutate other identical objects): "An object has ValueSemantics when it can be treated as a single value. In CeePlusPlus this means implementing a copy constructor and an assignment operator in such a way that when a new or existing instance is set equal to some other instance the new instance will be equivalent to the old one without acting as an alias to it." – Géry Ogam Apr 10 '20 at 01:44
  • My reasoning for saying that the identity definition of value semantics implies the assignment definition (and the reciprocal) is the following. If object identity is based on state, taking two identical *value objects* means that they are logically identical (in state) but physically different (in location), so they cannot physically mutate each other. And if object identity is based on location, taking two identical *reference objects* means that they are logically different (in state) but physically identical (in location), so they can physically mutate each other. Does it make sense? – Géry Ogam Apr 10 '20 at 02:25
  • @Maggyero Interesting thoughts. I think your point about assignment is true in a pure mathematical world, where values exist, and objects/variables are only a way to designate a value. In such a world you have no clones. The world I used for my definition is closer to the real world: I can have two clones which have the same meaning for me. Take a 1€ coin: The amount of coins have the same meaning for me, and I don’t care for the physical coins. This is a world where clones can exist. In C++ hou have the choice, and can decide to care for the address/reference of the object (the physical coin) – Christophe Apr 10 '20 at 09:44
  • @Maggyero or you can decide to care only for the value. In real world you also have the choice: a numismatic fanatic will look at every coin for its own identity (and defaults, scratches history), whereas most of the people care only for the value. So it’s more philosophy than mathematics ;-) Your last sentence is confusing and I think something is missing: if identity is based on location, to identical references are always referring to the same object: it’s the same coin. If you mutate it by making a scratch on the coin, all the references will have the same scratch. Therefore ... – Christophe Apr 10 '20 at 09:49
  • @Maggyero ... I suppose you mean “different (in state) at a different moment)” and that you are meaning the historical evolution of the object ? – Christophe Apr 10 '20 at 09:51
  • 1
    Sorry for the sloppy explanation, for the last sentence I meant logically and physically identical. Better explanation: in both cases, I take two objects, distinct in address (memory) but identical in contents (bytes). That contents represents a value for *value objects* and a reference to a target contents for *reference objects*. So mutating the contents of a value object is *not* visible to the other value object (since they have distinct adresses). But mutating the *target* contents of a reference object is visible to the other reference object (since they refer to the same contents). – Géry Ogam Apr 10 '20 at 12:52
  • So far we have been talking about the definition of value/reference semantics and value/reference objects. Now about the definition of value/reference type, you said "This means that every object created with the type has the semantic of the type." As Theraot noted in his answer, this seems only partially true, because a value type can have reference semantics (for instance [a struct with a reference member to a mutable object](https://stackoverflow.com/a/945708/2326961) in C++ or C#) and a reference type can have value semantics (for instance a reference to an immutable object in C++ or C#). – Géry Ogam Apr 10 '20 at 14:07
  • 1
    @Christophe, the distinction is not merely philosophical. In (mathematical) algebra, a name is bound to a value only at evaluation time, and it acts much like an alias for the value. In programming, names aren't bound to values, they are bound to storage locations. And when a name is assigned to another name, there are at least 2 different ways of conceiving that operation: (a) aliasing the same storage location, (b) introducing a new storage location and copying the value. In mathematics, their sloppy notion of storage has no such distinction (just as they have no notion of pointers). – Steve Apr 10 '20 at 15:59
  • Let me come back to what I said earlier: value semantics = object whose identity is based on its state = object that cannot mutate other identical objects. I am not sure anymore of the last relation. Two identical structs with a member reference to the same mutable object have an identity based on their state, yet they can mutate each other through the member reference. So an object whose identity is based on its state does not imply that it cannot mutate other identical objects. The reciprocal is false too: two identical pointers to an immutable object have no identity based on their state. – Géry Ogam Apr 10 '20 at 21:32
  • Bjarne Stroustrup provides [another definition](https://books.google.fr/books?id=We21AwAAQBAJ&pg=PA637&lpg=PA637&dq=“value+semantics%22+%22deep+copy%22&source=bl&ots=og1J80pkdW&sig=ACfU3U1bgBVssrqw6r_Rxecx22P5FgycRg&hl=fr&sa=X&ved=2ahUKEwjMj7qQ3t7oAhXrDmMBHaypClMQ6AEwDnoECAwQKw#v=onepage&q=“value%20semantics%22%20%22deep%20copy%22&f=false) for *value/reference semantics*: types providing *deep/shallow copy*. For instance `int` and `string` have value semantics while `int*`, `int&`, `string*` and `string&` have reference semantics. How does it relate to our *state/location identity* definition? – Géry Ogam Apr 10 '20 at 21:48
  • @Maggyero I’m an eager reader of the whole work of Stroustrup, starting with his first book on C++ in the early nineties. This is certainly why I gave so much C++ examples. In fact my points are aligned on that: int* and string* are pointers; int& and string& are references. int and string on contrary have value semantics, which means that the clones with same value are equal. The constraint on seep copy is about assignment: it says that assignment should work with clones so that the two values remain independent: members of a value object should not leak references – Christophe Apr 10 '20 at 22:07
  • I really like Stroustrup’s work too though I haven’t read a lot. Deep copy copies the values referred to so it implies state equality, and shallow copy copies the adresses so it implies location equality. The reciprocal works too. So deep/shallow copy is equivalent state/location equality. But state/location equality is not synonym of equality *based on* state/location, which was our definition of value/reference semantics. Having state/location equality does not mean the equality operator of the type is defined one or the other way. So how do we resolve that issue? @Steve you are welcome too. – Géry Ogam Apr 10 '20 at 22:55
  • @Maggyero, I'm not sure I understand your last sentence. Whether equality is based on value or on address, depends precisely on how the equality operator is defined. – Steve Apr 11 '20 at 00:36
  • @Maggyero the deep copy aims to ensure that every copy is completely independent. This is indeed a very good illustration of the value semantic when using pointers which are used to implement reference semantic, but are in reality themselves values. If you have two clones (with pointers literally copied) they would pass the value comparison test. But you’re not really doing a value comparison because you compare the pointer value and not the pointed object. So for a real value comparison, you should compare not pointers, but dereferenced pointers. If you do so, the comparison will pass also... – Christophe Apr 11 '20 at 08:44
  • @Maggyero ... for deep copy. And this is an example why it makes sense to override assignment in a value type in C++: to make sure that the right semantic that you want to associate with a type is performed. If values would me unmutable in C++ we would not need to do this. But C++ lets you mutate values as well: so only deep copy ensures value semantic: otherwise a side effect when modifying one object would modify also the value of an independent object (typical reference semantic behavior). So after all maybe mutability/unmutability should influence def of val type/object. – Christophe Apr 11 '20 at 08:57
  • Stroustrup’s illustration is indeed excellent. His pointer diagrams {p->88<-q} and {p->88, q->77} show that in the first case the pointers are dependent on each other and in the second case they are independent from each other. I have just realised that it is this *independency/dependency* that defines value/reference semantics instead of deep/shallow copy which is just a means to achieve independency/dependency. – Géry Ogam Apr 11 '20 at 21:24
  • This is consistent with the [C2 definition](https://wiki.c2.com/?ValueSemantics): "An object has ValueSemantics when it can be treated as a single value." and [Gallagher’s definition](https://academy.realm.io/posts/swift-gallagher-value-semantics/): "Value semantics amounts to being a guarantee of the independency of the value of variables. However the problem with the C2 and Gallagher’s definition is that they are *absolute* instead of relative. – Géry Ogam Apr 11 '20 at 21:25
  • I think that defining value semantics for a *single* object is eventually not that much relevant, since an object independent in isolation just means that it is immutable (otherwise one can always create a pointer to the object and mutate it). That is why I propose a *relative* definition of *value/reference semantics*: an independency/dependency *relation* between objects. For instance the pointers in Stroustrup’s diagrams are not independent/dependent in isolation but with respect to each other. – Géry Ogam Apr 11 '20 at 21:26
  • Besides Stroustrup’s diagrams, what set me thinking in the relativity of the concept is [Goodwin’s insisting](https://wiki.c2.com/?ValueObjectsCanBeMutable) on preserving value semantics *between objects*: "Are ValueObjects simply objects that preserve ValueSemantics or is there something more to them?" With this new definition, a reference semantics relation between objects is equivalent to being shallow equal (like {p->88<-q} in Stroustrup’s illustration). – Géry Ogam Apr 11 '20 at 21:26
  • There are also sufficient conditions for value semantics: if the objects are deep copies of one another, or if they are shallow copies of one another with copy-on-write mechanisms, or if they are shallow copies of one another with references to immutable objects. And there is also a sufficient condition for reference semantics: if the objects are shallow copies of one another. – Géry Ogam Apr 11 '20 at 21:27
  • This is consistent with [Goodwin’s analysis](https://wiki.c2.com/?ValueObjectsCanBeMutable): "Making value objects immutable solves this problem by forcing the developer to create a new object every time some aspect of the ValueObject's state changes. This is certainly a viable solution but it is not the only one available." and "ValueSemantics for objects-by-value are preserved by copying values between objects. ValueSemantics for objects-by-reference are preserved by using a CopyOnWrite mechanism." – Géry Ogam Apr 11 '20 at 21:27
  • Following from this, I propose this definition of a *value/reference type*: a type that provides deep/shallow copy (so that *copies* are in value/reference semantics relation) and *optionally* deep/shallow equality (for consistency with the value/reference semantics relation of the copies). This type definition is what Stroustrup calls value/reference semantics, but for us deep/shallow copy is just one of several ways to realise value/reference semantics to which I gave a more general definition. – Géry Ogam Apr 11 '20 at 21:27
  • Finally I propose this definition of a *value/reference object*: an instance of a value/reference type. This definition is consistent with [Goodwin’s](https://wiki.c2.com/?ValueObject): "I'm inclined to think that they are defined in C++ as objects that override the copy constructor, assignment and comparison operators to assign and compare state between two objects." – Géry Ogam Apr 11 '20 at 21:28
  • 1
    @Maggyero Interesting thoughts. I’d suggest to cross check if the definitions hold with other languages as well. It seems that you have collected enough material to write an article on your own ;-) Thanks for the fruitful exchange. And please, post a link here to your future article when it’s ready – Christophe Apr 11 '20 at 21:35
  • 1
    Thank you Christophe, I will. Your answer and our discussion during this week were extremely interesting and helpful to shape these definitions (if you find any inconsistency, I am interested in your feedback). Thanks you @Steve as well =) About writing an article, I guess you mean a blog article, not a research article (since there is no discovery, just a gathering and making sense of a bunch of more or less consistent/precise definitions), right? – Géry Ogam Apr 11 '20 at 21:57
1

In looking at these terms, we must appreciate that these terms are overloaded, and at various levels of abstraction.

We have broad and common sense usages of these terms, and then we have some of these terms defined by DDD (Domain Driven Design), and then also by various programming languages.

The definitions by programming languages are specific and precise each for their individual language.  For example, Java has primitive types which are value types, exhibit value semantics, etc..  It traditionally has not had user-defined value types, but substitutes the use of immutable object types, such as with the string class — however all objects have a location that can be observed (by pointer equality comparison), including strings and other immutable types.

DDD defines Value Objects as objects without identity, but doesn't define Value Types.

C# offers user-defined value types, but these can be mutated, and you can observe the location of them.

(C++ is whole other can of worms, with its own terms & rules.)

Reference types give use references to objects rather than "reference objects" per se — which is just terminology, I think.

I would agree with your other thoughts, though modulo the context your working in as per the above.

  • Yes, value types give value objects
  • Yes, value objects have value semantics
  • Yes, reference types have reference semantics, which implies mutability, the need to manage object lifetime (perhaps by reference counting), the need for synchronization, etc..
Erik Eidt
  • 33,282
  • 5
  • 57
  • 91
  • "DDD defines Value Objects as objects without identity" - a small correction (and a bit more info for the benefit of the OP): value objects in this meaning are objects with identity entirely defined by the combined value of their properties, in the sense that nothing changes if you get a different instance (a different copy with the same values of the properties), or, say, when you save to storage, if you completely discard the old data (e.g. delete table rows, or existing entries in some other kind of storage) and replace it with some new data, etc. – Filip Milovanović Apr 08 '20 at 18:46
  • Thanks Erick for this overview. "reference types have reference semantics, which implies mutability" Mutability of the reference or the target? – Géry Ogam Apr 08 '20 at 20:09
  • @FilipMilovanović Thanks Filip for the correction. "value objects in this meaning are objects with identity entirely defined by the combined value of their properties, in the sense that nothing changes if you get a different instance" Nothing changes for a procedure applied to the value object? Doesn’t it mean that you are defining the value semantics *of the procedure*, with respect to its parameter, instead of the value semantics of the value object itself? – Géry Ogam Apr 08 '20 at 20:36
  • @Maggyero, mutability of the object that is the target of a reference, since in this discussion, that is what is being shared by callers/callees, or, even multiple threads. – Erik Eidt Apr 08 '20 at 20:45
  • Alright. But I don’t understand this implication: can’t we have an immutable reference type (either immutable reference or immutable target)? For instance a constant pointer to integers (`int* const`) or a pointer to constant integers (`int const*`) in C++. – Géry Ogam Apr 08 '20 at 20:51
  • @Maggyero "Doesn’t it mean that you are defining the value semantics of the procedure" - Not exactly. In DDD terms, this is values vs entities: This is about domain modeling (how you represent and think about the problem you are solving); the distinction is made because you have to treat entities with greater care. The procedure itself will not necessarily be affected; instead, there will be some side effect that could affect other parts of the system - inconsistent or corrupt data, buggy behavior, broken references, things like that. Values you can just discard and replace. – Filip Milovanović Apr 08 '20 at 21:46
  • @Maggyero There are two related but subtly different concepts here (that slightly overlap); the conceptual distinction between values and entities (Domain Driven Design terminology), and pass-by-value vs pass-by-reference. This other thing is about what happens when you pass objects in and out of functions (basically, copy vs pointer). Now, some languages, like C#, bake that into the type system, so they have value types & reference types as two different categories of types. Others provide support at the syntax level (e.g. MyType vs MyType*). – Filip Milovanović Apr 08 '20 at 21:46
  • @Maggyero "can’t we have an immutable reference type" - you can; in C# `string` is an immutable reference type with, as far as any client code is concerned, value semantics (at least, in most circumstances). – Filip Milovanović Apr 08 '20 at 21:46
  • At the programming language level, yes, we can have an immutable reference type, but at the domain level, it is immaterial whether an immutable is treated as value type or reference, so these are mixing concepts from different levels of abstraction. – Erik Eidt Apr 08 '20 at 21:57
0

After discussing @Christophe’s and @Theraot’s excellent answers, and drawing inspiration from Bjarne Stroustrup’s and Phil Goodwin’s definitions, I finally came to the following set of definitions, that are close but slightly different (more general) from the previous authors’:

  • Value/reference semantics. — An independency/dependency relation between objects.
  • Value/reference type. — A type that provides copies in value/reference semantics relation.
  • Value/reference object. — An instance of a value/reference type.

Sufficient conditions for value semantics:

  • the objects are deep copies of one another, or
  • the objects do not hold references and are shallow copies of one another, or
  • the objects do not hold references to mutable objects, hold references to immutable objects and are shallow copies of one another, or
  • the objects hold references to mutable objects, hold references to immutable objects and are mutable-deep and immutable-shallow copies of one another.

Sufficient condition for reference semantics:

  • the objects hold references to mutable objects and are shallow copies of one another.

Feel free to give your feedback in comments.

Playground

Memory layout resulting from assignment in C++:

int i{3};              // i:3
int j{i};              // i:3 j:3 (copy of i: j)

int* p{&i};            // i:3 p:&i (alias of i: *p)
int* q{p};             // i:3 p:&i q:&i (copy of p: q, alias of i: *q)
int* r{new int{*p}};   // i:3 p:&i *r:3 r:_ (copy of i: *r)

int** s{&p};           // i:3 p:&i s:&p (alias of p: *s)
int** t{s};            // i:3 p:&i s:&p t:&p (copy of s: t, alias of p: *t)
int** u{new int*{*s}}; // i:3 p:&i s:&p *u:&p u:_ (copy of s: *u, alias of p: **u)

Here i and j are in value semantics relation, p an q are in reference semantics relation, p and r are in value semantics relation, s and t are in reference semantics relation, and s and u are in reference semantics relation.

Géry Ogam
  • 602
  • 3
  • 13
  • I would broadly agree with these definitions, but I'm not sure it makes sufficiently explicit what is meant by "dependency" or "object". It's not necessary for copies to be deep for a thing to be of value type - your postal address can be treated as a value, without having to copy the contents of your house also. To put it another way, the question is not whether the value contains references, it's whether the value *is subject to* (or to be yet clearer, *is the target of*) multiple references or not. If the assignment operation causes multiple references by default, it is a reference type. – Steve Apr 14 '20 at 12:56
  • I think another complication is that you're looking at this in a very object-oriented way, without realising that this distinction is more fundamental than the object-oriented pattern - objects are a kind of reference type, and values are *not* objects. If a "value object" has any consistent definition, it is simply a reference object that will be employed in a *referentially transparent* way - it says nothing about whether or how that transparency will be enforced. – Steve Apr 14 '20 at 13:13
  • Hi @Steve! Thanks for your feedback. "It's not necessary for copies to be deep for a thing to be of value type" Just before you posted I updated the definition of value type which was restricted to deep copy like Stroustrup’s to allow any kind of copies, as long as they are in value semantics relation (sufficient conditions for value semantics are given below the definitions), that is independent copies. "what is meant by dependency" I mean that the mutation of one object does not affect another object in the value semantics relation. – Géry Ogam Apr 14 '20 at 23:21
  • 1
    I note your definitions have changed since I first commented. In my view the deep copy issue is a bit of a grey area, and would depend on whether pointers themselves are treated as values. In my understanding, pointers could be treated as true cross-reference values, not just as referential links to a subsidiary area of the same composite value object. – Steve Apr 14 '20 at 23:49
  • @Steve "it's whether the value *is subject to* (or to be yet clearer, *is the target of*) multiple references or not" Since a value can always be the target of a reference (by just creating a pointer to it), I guess you are only talking about the references that are part of the value semantics relation under discussion. "To put it another way, the question is not whether the value contains references" If the value contains a reference to a mutable value of the relation, the two values will not be independent so they will be in reference semantics relation. So I don’t understand here. – Géry Ogam Apr 14 '20 at 23:50
  • 1
    obviously a value is always the target of at least one reference, otherwise it would be unreachable. That's why I emphasise the distinction of whether assignment results in *multiple* references or whether it results in a copied value. As for a value containing a reference to something mutable, the question is whether that mutable thing is treated as part of the value or not. For example, an integer representing a database key is ultimately a reference (albeit not an in-memory reference), but that reference is probably treated as being external...(1/2) – Steve Apr 14 '20 at 23:59
  • 1
    (2/2)... Thus, a value object representing a database row is still treated as a value object, notwithstanding that it contains a reference to mutable data elsewhere. – Steve Apr 15 '20 at 00:03
  • @Steve "That's why I emphasise the distinction of whether assignment results in multiple references or whether it results in a copied value." Hmmm interesting, the funny thing is that this morning I was thinking again about your name binding remark from Friday in the comment section of Christophe’s answer. So if I understood you correctly, name binding to a specific storage location at assignment can also influence value/reference semantics, besides whether the contents of the storage location itself holds references or not? And you even go further by saying that *only* name binding counts? – Géry Ogam Apr 15 '20 at 00:42
  • @Steve If the kind of name binding defines value/reference semantics as you state, in C++ it means that pointers have value semantics (since assignment results in multiple storage locations with one name bound to each—binding by copy) while references have reference semantics (since assignment results in one storage location with multiple names bound to it—binding by aliasing). While in Python and Java it means that all types have reference semantics (since assignment results in one storage location with multiple names bound to it—binding by aliasing). Do you agree? – Géry Ogam Apr 15 '20 at 01:10
  • So in Java if I have an int variable 'a', and assign it to int variable 'b' - that is, b=a - that results in an alias rather than a copy value? I think not. As for the C++ reference, yes undoubtedly that is a reference type, although I believe at the implementation level it is a copy-by-value pointer - in this case, the compiler does a lot of heavy lifting to conceal the implementation and make a pointer seem like an alias. – Steve Apr 15 '20 at 09:17
  • @Steve According to the Java specification, it seems that you are right: [4.1](https://docs.oracle.com/javase/specs/jls/se14/html/jls-4.html#jls-4.1) "There are two kinds of types in the Java programming language: primitive types (§4.2) and reference types (§4.3). There are, correspondingly, two kinds of data values that can be stored in variables, passed as arguments, returned by methods, and operated on: primitive values (§4.2) and reference values (§4.3)." – Géry Ogam Apr 15 '20 at 12:09
  • … [4.12](https://docs.oracle.com/javase/specs/jls/se14/html/jls-4.html#jls-4.12) "A variable is a storage location and has an associated type, sometimes called its compile-time type, that is either a primitive type (§4.2) or a reference type (§4.3). A variable's value is changed by an assignment (§15.26) or by a prefix or postfix ++ (increment) or -- (decrement) operator (§15.14.2, §15.14.3, §15.15.1, §15.15.2)." – Géry Ogam Apr 15 '20 at 12:10
  • … [4.12.1](https://docs.oracle.com/javase/specs/jls/se14/html/jls-4.html#jls-4.12.1) "A variable of a primitive type always holds a primitive value of that exact primitive type.", [4.12.2](https://docs.oracle.com/javase/specs/jls/se14/html/jls-4.html#jls-4.12.2) "A variable of a class type T can hold a null reference or a reference to an instance of class T or of any class that is a subclass of T. A variable of an interface type can hold a null reference or a reference to any instance of any class that implements the interface." – Géry Ogam Apr 15 '20 at 12:10
  • @Steve Thus in Java (and in C++, and maybe in all programming languages?) a *variable* is a *storage location* (memory address). Different attributes can be bound to it: a *name*, a *type*, a *value*. The value bound to (stored in) a variable can represent an entity or a reference to an entity. But now I am wondering what we really mean by *name binding*? Is it the association of a name to a variable (storage location) like I have just said, or the association of a name to an entity? – Géry Ogam Apr 15 '20 at 12:59
  • 2
    I think your terminology may be becoming muddled. The two basic elements are the storage location and the value - every storage location has a value, and every value has a storage location. Names are aliases for storage locations, and additionally may have a type annotation, both of which exist only in source code, not in compiled code. A value is not bound to a variable - a name is bound to a storage location, and a storage location stores a value. Placing a value into a storage location is an assignment operation...(cont'd) – Steve Apr 15 '20 at 13:23
  • 1
    ...An "entity" does not exist either at the machine level or the source code level. Arguably, it's a word completely equivalent to "thing", a word empty of meaning in itself but which forms a placeholder in a sentence structure, which means the listener must imply the meaning. *Name binding* means to associate a name with a storage location. – Steve Apr 15 '20 at 13:33
  • I should add as well, Java is a modern object-oriented language whose terminology and concepts may not always exactly be in harmony with the reality of implementation. For example, a "null reference" typically means "a storage location with a zero value", where the compiler understands that that storage location is used to store a value of pointer type. Zero is used as a convention to mean a pointer with no valid target. – Steve Apr 15 '20 at 13:47
  • @Steve So if name binding means associating a name to a storage location (not an entity), [this article](https://cs.lmu.edu/~ray/notes/bindings/) is completely wrong. – Géry Ogam Apr 15 '20 at 13:51
  • Well it's *not wrong* if you substitute the word "thing" for every use of "entity" - in fact I've just entertained myself for a minute doing exactly this - but you'll quickly realise that that author's problem is that he's not being specific about the nature of the *thing* to which he refers. He confounds matters to the extreme when he talks of polymorphism. – Steve Apr 15 '20 at 14:09
  • @Steve It seems that the author (Raymond Toal) uses "entity" to mean a storage location *holding a non-reference value*. So for a pointer named `p`, he never talks about the binding of `p` with the reference storage location, only about the binding of `*p` with the target storage location (but what if the target storage location is itself a reference, does he then only talk about `**p`?). With his name binding definition (= to an entity), *mutation* of the reference of the pointer is *name rebinding* (to another target). With your definition (= to *any* storage location), only mutation exists. – Géry Ogam Apr 15 '20 at 17:05
  • 1
    I'm not convinced any reliance should be placed on what he says. I can only talk in rules of thumb, but people who draft a written work around use of the word "thing" or its synonyms, cannot usually be trusted to know what they're talking about. In my schema, only mutation exists because that is all that does exist. To rebind a name must mean to employ an existing name to alias a different storage address. Since names cease to exist after compilation, that cannot be a runtime operation. What he means by rebinding a name is *mutating a pointer value*. – Steve Apr 15 '20 at 17:31
  • @Steve I see. Now back to your value/reference semantics definition, you said "That's why I emphasise the distinction of whether assignment results in multiple references or whether it results in a copied value." I think the difficulty is to define what we mean exactly by "multiple references" and "copied value"? For "multiple references", do we mean multiple names bound to the same storage location, or multiple reference storage locations with the same target storage location? For "copied value", do we mean the reference or target storage location of a pointer in case of pointer assignment? – Géry Ogam Apr 15 '20 at 17:59
  • @Steve For "multiple references", since names do not exist at runtime, I guess that we mean multiple reference storage locations referring to the same target storage location. For "copied value", I guess that we mean a copy of the *target* storage location of a pointer in case of pointer assignment. But what if that target storage location is itself a pointer? Do we still consider a copy of that target storage location as a "copied value"? – Géry Ogam Apr 15 '20 at 18:57
  • good question, and it shows that I'm being sloppy with terminology (in danger, in fact, of showing that I can't be trusted to know what I'm talking about!). By multiple references, I meant "multiple pointer values, stored in multiple storage locations, pointing to the same target storage location", and not "multiple names bound to the same storage location". For "copied value", I meant "any value being copied other than a hidden pointer value employed in the implementation of a reference type"!... (cont'd) – Steve Apr 15 '20 at 19:02
  • ...The problem is that I hadn't explained priorly how assignment of reference types are implemented, firstly in terms of pointer values being copied, and secondly in terms of the very existence of those pointer values being systematically concealed from the programmer by the programming language. In other words, a reference type is built from the pointer value type, but the syntax is modified so that the existence of the pointer is not acknowledged, so that it appears as though the name is bound directly to the base address of the object, rather than bound to a pointer.... (cont'd) – Steve Apr 15 '20 at 19:15
  • ...And the pretence is maintained systematically, so that whereas the name appears to be bound to the base address of the object (i.e. there is no syntactic indication that a pointer is involved), in fact it is bound to the storage address of the unacknowledged pointer, and therefore an assignment operation copies *the pointer* by value, rather than the object itself by value. – Steve Apr 15 '20 at 19:22
  • As an aside, I had originally wanted to write a comprehensive answer on this, but once I got to multiple pages of text tackling all the background of how object oriented concepts are implemented, and without at that point coming to a conclusion, I threw it all away! – Steve Apr 15 '20 at 19:28
  • @Steve Your explanation was exactly what I had in mind. 'For "copied value", I meant "any value being copied other than a hidden pointer value employed in the implementation of a reference type"!’ So even if the value being copied is itself a pointer value (an address)? – Géry Ogam Apr 15 '20 at 21:41
  • 1
    Exactly. The very hallmark of a reference type, is that assignment results in the copy-by-value of the pointer. The confounding thing in many languages like Java is that there is no syntactic evidence that this layer of indirection even exists - it's all done under the bonnet. – Steve Apr 15 '20 at 23:55
  • @Steve So, doesn’t your definition mean that shallow copies (and deep copies of course) are in value semantics relation? – Géry Ogam Apr 16 '20 at 00:04
  • 1
    Shallow copies of which thing? And what exactly does it mean for copies to be "in value semantics relation"? – Steve Apr 16 '20 at 00:13
  • @Steve Would you like to join Theraot and I [in the chat](https://chat.stackexchange.com/rooms/106728/discussion-between-theraot-and-maggyero)? – Géry Ogam Apr 16 '20 at 00:24