Related
This might seem like a silly question, but I want to make a struct with a collection of functions, but the functions bind to the struct. I can sorta see that this is a cycle, but humor me with this example:
type FuncType func() error
type FuncSet struct {
TokenVariable int
FuncTyper FuncType
}
and I want to be able to create a function bound to the FuncSet type so it can operate on TokenVariable, thusly:
func (f *FuncSet) FuncType() error {
f.TokenVariable = 100
return nil
}
However, this changes the signature of the type (I can't find any information about type bindings as part of function type specifications) such that assigning this function to the struct element tells me this function/variable is not found.
I can see an easy work-around for this, by prefixing the parameters with a pointer to the struct type, it's just a bit ugly.
I looked around a little further and discovered that what I'm kinda looking for is like a closure in that it can be passed a variable from the immediate outer scope but... well, I'll be glad to be corrected about this absence of type binding in function types, but for now passing the pointer to the type looks like the way to go.
I think I found the solution:
type nullTester func(*Bast, uint32) bool
type Bast struct {
...
isNull nullTester
...
}
func isNull(b *Bast, d uint32) bool {
return d == 0
}
and then I can bind it to the type like this:
func NewBast() (b *Bast) {
...
b.isNull = isNull
...
}
// IsNull - tests if a value in the tree is null
func (b *Bast) IsNull(d uint32) bool {
return b.isNull(b, d)
}
It seems a bit hackish and I'm not sure what's going to happen in a second library that I will write that sets a different type for the uint32 parameter, but go vet is happy so maybe this is the correct way to do it.
It does seem to me that func types should really have a field in the grammar to specify a binding type, but maybe I just found a hack that sorta lets me do polymorphism. In calling programs all they will see is the nice exported function that binds to the type as planned and I get my readability as well as being able to retarget the base library to store a different type of data.
I think this is the proper solution. I just can't find anything that confirms or denies whether in a type Name func specification there is any way of asserting the type. It really should not match up, since the binding is part of the signature, but the syntax for type with functions does not appear to have this type binding.
My actual code is here, and you can see by looking at it what I am aiming to do:
https://github.com/calibrae-project/bast/blob/master/pkg/bast/bast.go
The differences between the type of data the tree stores is entirely superficial, because it is intended to be primarily used for sorting unsigned integers of various lengths, and one important thing it needs to have is to be able to work from a, for example, 64 bit integer but sort only by the first or last half (as I have a bigger project that treats these hash values as coordinates in an adjacency list). In theory it could be used instead of a hash table lookup as well, with a low variance in time to find elements because of the binary tree structure.
It's not a conventional, reference-vector based tree, and the store itself is an array with an unconventional power of two mapping, a 'dense' tree, and the purpose above all, for implementing this way, is that when the tree is walked, as well as rotated, much of the time it is sequential blocks of memory being accessed which should make for a lot less cache misses than a conventional binary tree (and for which reason generally this type of application just uses some kind of sort like a bucket sort).
You could use an anonymous field with an interface that defines the method set that you want to use (that might change).
Go playground here
You'd define your interface
type validator interface {
IsRightOf(a, b interface{}) bool
... // other methods
}
and your type:
type Bast struct {
validator // anonymous interface field
... // some fields
}
Then you can access the methods of validator from the Bast type
b := bast.New()
b.IsRightOf(c, d) // this is valid, you do not need to do b.validator.IsRightOf(...)
because validator is an interface you can change those methods how you like.
import std.stdio;
class IntegerContainer
{
public int Integer = 1;
}
void DoubleInteger(IntegerContainer Container)
{
Container.Integer *= 2;
}
void main()
{
IntegerContainer Container = new IntegerContainer; // Internal integer defaults to one.
DoubleInteger(Container); // Internal integer changes to two inside the function.
writefln(Container.Integer); // Prints "2."
}
In D, reference vs. value is a trait of the type, rather than of the function parameter. Coming from C++, this feels really bad to me.
It looks like there's a ref keyword to force pass-by-reference for functions accepting structs. Is there such an equivalent for passing classes by value?
For example, let's say I want to make a function function that returns a sorted copy of a custom container class. In C++, that's as simple as using Foo Sorted(Foo Object), as opposed to Foo Sort(Foo& Object). I see no way of doing this in D without manually copying the object.
Classes are reference types by design. They're not supposed to be passed by value. It's exactly the same with Java and C#. However, unlike Java and C#, D has full-fledged user-defined value types as well, since it has structs (C# has structs too, but they're much more limited). The fact that C++ conflates the two causes problems such as object slicing.
Now, obviously there are times when you want to copy a reference type. The solution to that is cloning. You give your class a clone function which returns a copy of the object it's called on. That way, you can copy it when you need to, and it only gets copied when you need it to be. Java and C# have a standard clone function that most types implement, but for whatever reason D does not. I'm not sure why. But it's still easy enough to declare such a function yourself for your own types. It just isn't going to be on Object, which would allow you to use it on pretty much any class object without caring what the actual type was like you can do in Java and C#. You could always create a copy constructor instead, if you prefer, but it's less flexible, because you have to know the type of the object being copied, whereas with clone, it can be any type derived from the type that clone returns (which would be Object in the case of Java and C# but would be whatever you decide in D, since the function is non-standard).
Yeah, just use a struct instead of a class.
But if you want to copy an object, then you have to implement cloning yourself. Note that the D designers didn't make this up; it's the exact same way in C#, and pretty similar in Java. The goal is to prevent objects from being copied excessively, which is seen as a downside of C++ (since it's very hidden in the code).
Even in C++ this:
Foo Sorted(Foo Object)
is not that useful. What if the Object is already sorted and you don't need to create a copy?
In D you will need to provide clone() of some such for your class and call it if needed.
Otherwise use structs as Mehrdad mentioned.
Edit: It is not clear what exactly "copying the object" should do. If it has array of objects inside shall it clone that array? And what about object references it contains? It is actually good that monsieur Walter Bright, author of D, did not provide copying of class instances by default.
Please tell me why the constructor does not return any value. I want a perfect technical reason to explain to my students why the constructor does not have any return type.
What actually happens with the constructor is that the runtime uses type data generated by the compiler to determine how much space is needed to store an object instance in memory, be it on the stack or on the heap.
This space includes all members variables and the vtbl. After this space is allocated, the constructor is called as an internal part of the instantiation and initialization process to initialize the contents of the fields.
Then, when the constructor exits, the runtime returns the newly-created instance. So the reason the constructor doesn't return a value is because it's not called directly by your code, it's called by the memory allocation and object initialization code in the runtime.
Its return value (if it actually has one when compiled down to machine code) is opaque to the user - therefore, you can't specify it.
Well, in a way it returns the instance that has just been constructed.
You even call it like this, for example is Java
Object o = new Something();
which looks just like calling a "regular" method with a return value
Object o = someMethod();
How is a constructor supposed to return a return value? The new operator returns the newly created instance. You do not call a ctor, newdoes it.
MyClass instance = new MyClass();
If the ctor would return a value, like so:
public int MyClass()
{
return 42;
}
Where would you receive the integer?
(I'm biased towards C++, so regarding other languages, take this with a grain of salt.)
Short answer: You don't want to have to explicitly check for success for every single object construction in your code.
Somewhat longer answer: In C++, constructors are called for dynamically as well as for globally and automatically allocated objects. In this code
void f()
{
std::string s;
}
there is no way for the constructor of s (std::string::string()) to return any value. Either it succeeds - then we can use the object, or it throws an exception - the we never get a chance to try to use it.
IMO, that's the way it should be.
A constructor is some method automatically called when you initialize a new instance of an object.
This method is there if you need to initialize your object to a given state and run few default methods.
Actually you can imagine the constructor always return the instance of the object created that would be a good image.
When you call a constructor the return value is the new object:
Point pt = new Point(1,2);
But within the constructor itself, you're not actually creating and returning the object; it's been created before your code starts, you're just setting up the initial values.
Point::Point(int x, int y) {
this->x = x;
this->y = y;
}
The lack of a return type reflects the fact that constructors are used differently than other functions. A return type of null, while technically accurate, doesn't reflect well the fact that the code is used as if it returns an object. However, any other return type would indicate that your code is supposed to return something at the end, which is also incorrect.
Constructor doesn’t return anything not even Void. Though some of the answers have mentioned that Constructor do return reference to the newly created object , which is not true. It’s the new operator that returns the object.
So Why constructor doesn’t return any value
Because its not supposed to return anything. The whole purpose of constructor is to initialize the current state of the object by setting the initial values.
So Why doesn’t it even return Void
This is actually a Design constraint which has been placed to distinguish it from methods. public void className() is perfectly legal in java but it denotes a method and not a constructor. To make the compiler understand that it’s a constructor , it requires a way to distinguish it.
all answers are biased towards C++/Java. there is no reason a constructor does not return a value other than the language design.
look at a constructor in a broader sense: it is a function which constructs a new object. you can write perfectly valid constructors in C:
typedef struct object object;
int object_create( object **this );
this is perfect OOP in C and the constructor returns value (this can also be called a factory, but the name depends on the intention).
however, in order to create an object automatically (to satisfy some type cast, or conversion for example), there have to be some rules defined. in C++, there is an argument-less constructor, which is inferred by the compiler if it is not defined.
the discussion is broader than what we think. Object Oriented Programming is a name which describes a way of thinking about programming. you can have OO in almost any language: all you need is structures and functions. mainstream languages like C++ and Java are so common that we think they define "the way". now look at the OO model in Ada: it is far from the model of C++ but is still OO. i am sure languages like Lisp have some other ways of doing OO.
One point that hasn't yet been discussed is that the constructor of class "foo" must be usable not only when creating instances of foo, but also when creating instances of classes derived from foo. In the absence of generics (which weren't available when Java, C++, or .net were designed) there would be no way for foo's constructor to return an object of any derived class. Therefore, what needs to happen is for the derived-class object to be created via some other means and then made available to foo's constructor (which will then be able to use the object in question as a foo when doing its initialization).
Even though the VM implementation of a constructor isn't to return any value, in practice it kind of does - the new object's reference. It would then be syntactically weird and / or confusing to be able to store one or both of the new object's reference and an additional return value in one statement.
So the reason the constructor doesn't return a value is because it's not called directly by your code, it's called by the memory allocation and object initialization code in the runtime. Its return value (if it actually has one when compiled down to machine code) is opaque to the user - therefore, you can't specify it.
Constructor is not directly called by the user's code. It's called by the memory allocation and object initialization code in the run time. Its value is not visible to the user.
In case of C#, the syntax for declaring object is :
classname objectname= new constructor();
According to this line, if we are using assignment operator(=) then it should return some value. But the main objective of a constructor is to assign values to variables, so when we use a new keyword it creates instance of that class, and constructor assigns values to the variable for that particular instance of object, so constructor returns assigned values for that objects's instance.
We can not call constructors independently. Instead they are automatically called whenever objects are created.
Ex:
MyDate md = new Mydate(22,12,2012);
In above example new will return a memory location which will be held by md, and programatically we can not return multiple values in single statements.
So constructors can not return anything.
From what I know about OO design methodologies, I would say the following:
1)By allowing a constructor to return a value, framework developer would allow the program to crash in an instant where the returned value is not handled. To keep the integrity of the program workflow, not allowing a return value from the initialization of an object is a valid decision. Instead, language designer would suggest/force the coders to use getter/setter - access methods.
2)Allowing the object to return a value on initialization also opens possible information leaks. Specially when there are multiple layer or access modifications applied to the variables/methods.
As you aware that when object is created constructor will be automatically called So now imagine that constructor is returning an int value. So code should like this...
Class ABC
{
int i;
public:
int ABC()
{
i=0;
return i;
}
.......
};
int main()
{
int k= ABC abc; //constructor is called so we have to store the value return by it
....
}
But as you aware that stament like int k= ABC abc; is not possible in any programming language. Hope you can understand.
i found it helpful
This confusion arises from the assumption that constructors are just like any other functions/methods defined by the class. NO, they are not.
Constructors are just part of the process of object creation. They are not called like other member functions.
I would be using Java as my language in the answer.
class SayHelloOnCreation {
public SayHelloOnCreation() {
System.out.println("Hello, Thanks For Creating me!");
}
}
class Test {
public static void main(String[]args) {
SayHelloOnCreation thing = new SayHelloOnCreation(); //This line here, produces an output - Hello, Thanks For Creating me!
}
}
Now let us see what is happening here. in java, we use the new keyword to create an instance of a class. And as you can see in the code, in the line, SayHelloOnCreation thing = new SayHelloOnCreation();, the expression after the assignment operator runs before assignment is done. So using the keyword new, we call the constructor of that class (SayHelloOnCreation()) and this constructor creates an object on the Java Heap. After the object is created, a reference to that object is assigned to the thing reference of type SayHelloOnCreation.
The point that I am trying to keep here is that if constructors were allowed to have a return type, Firstly the strongly typed nature of the language would be compromised (Remember I am speaking about Java here).
Secondly, an object of class SayHelloOnCreation is created here so by default I guess the constructor returns a reference of the same type, to avoid ClassCastException.
A method returns the value to its caller method, when called explicitly. Since, a constructor is not called explicitly, who will it return the value to. The sole purpose of a constructor is to initialize the member variables of a class.
I read through the Wikipedia article Existential types. I gathered that they're called existential types because of the existential operator (∃). I'm not sure what the point of it is, though. What's the difference between
T = ∃X { X a; int f(X); }
and
T = ∀x { X a; int f(X); }
?
When someone defines a universal type ∀X they're saying: You can plug in whatever type you want, I don't need to know anything about the type to do my job, I'll only refer to it opaquely as X.
When someone defines an existential type ∃X they're saying: I'll use whatever type I want here; you won't know anything about the type, so you can only refer to it opaquely as X.
Universal types let you write things like:
void copy<T>(List<T> source, List<T> dest) {
...
}
The copy function has no idea what T will actually be, but it doesn't need to know.
Existential types would let you write things like:
interface VirtualMachine<B> {
B compile(String source);
void run(B bytecode);
}
// Now, if you had a list of VMs you wanted to run on the same input:
void runAllCompilers(List<∃B:VirtualMachine<B>> vms, String source) {
for (∃B:VirtualMachine<B> vm : vms) {
B bytecode = vm.compile(source);
vm.run(bytecode);
}
}
Each virtual machine implementation in the list can have a different bytecode type. The runAllCompilers function has no idea what the bytecode type is, but it doesn't need to; all it does is relay the bytecode from VirtualMachine.compile to VirtualMachine.run.
Java type wildcards (ex: List<?>) are a very limited form of existential types.
Update: Forgot to mention that you can sort of simulate existential types with universal types. First, wrap your universal type to hide the type parameter. Second, invert control (this effectively swaps the "you" and "I" part in the definitions above, which is the primary difference between existentials and universals).
// A wrapper that hides the type parameter 'B'
interface VMWrapper {
void unwrap(VMHandler handler);
}
// A callback (control inversion)
interface VMHandler {
<B> void handle(VirtualMachine<B> vm);
}
Now, we can have the VMWrapper call our own VMHandler which has a universally-typed handle function. The net effect is the same, our code has to treat B as opaque.
void runWithAll(List<VMWrapper> vms, final String input)
{
for (VMWrapper vm : vms) {
vm.unwrap(new VMHandler() {
public <B> void handle(VirtualMachine<B> vm) {
B bytecode = vm.compile(input);
vm.run(bytecode);
}
});
}
}
An example VM implementation:
class MyVM implements VirtualMachine<byte[]>, VMWrapper {
public byte[] compile(String input) {
return null; // TODO: somehow compile the input
}
public void run(byte[] bytecode) {
// TODO: Somehow evaluate 'bytecode'
}
public void unwrap(VMHandler handler) {
handler.handle(this);
}
}
A value of an existential type like ∃x. F(x) is a pair containing some type x and a value of the type F(x). Whereas a value of a polymorphic type like ∀x. F(x) is a function that takes some type x and produces a value of type F(x). In both cases, the type closes over some type constructor F.
Note that this view mixes types and values. The existential proof is one type and one value. The universal proof is an entire family of values indexed by type (or a mapping from types to values).
So the difference between the two types you specified is as follows:
T = ∃X { X a; int f(X); }
This means: A value of type T contains a type called X, a value a:X, and a function f:X->int. A producer of values of type T gets to choose any type for X and a consumer can't know anything about X. Except that there's one example of it called a and that this value can be turned into an int by giving it to f. In other words, a value of type T knows how to produce an int somehow. Well, we could eliminate the intermediate type X and just say:
T = int
The universally quantified one is a little different.
T = ∀X { X a; int f(X); }
This means: A value of type T can be given any type X, and it will produce a value a:X, and a function f:X->int no matter what X is. In other words: a consumer of values of type T can choose any type for X. And a producer of values of type T can't know anything at all about X, but it has to be able to produce a value a for any choice of X, and be able to turn such a value into an int.
Obviously implementing this type is impossible, because there is no program that can produce a value of every imaginable type. Unless you allow absurdities like null or bottoms.
Since an existential is a pair, an existential argument can be converted to a universal one via currying.
(∃b. F(b)) -> Int
is the same as:
∀b. (F(b) -> Int)
The former is a rank-2 existential. This leads to the following useful property:
Every existentially quantified type of rank n+1 is a universally quantified type of rank n.
There is a standard algorithm for turning existentials into universals, called Skolemization.
I think it makes sense to explain existential types together with universal types, since the two concepts are complementary, i.e. one is the "opposite" of the other.
I cannot answer every detail about existential types (such as giving an exact definition, list all possible uses, their relation to abstract data types, etc.) because I'm simply not knowledgeable enough for that. I'll demonstrate only (using Java) what this HaskellWiki article states to be the principal effect of existential types:
Existential types can be used for several different purposes. But what they do is to 'hide' a type variable on the right-hand side. Normally, any type variable appearing on the right must also appear on the left […]
Example set-up:
The following pseudo-code is not quite valid Java, even though it would be easy enough to fix that. In fact, that's exactly what I'm going to do in this answer!
class Tree<α>
{
α value;
Tree<α> left;
Tree<α> right;
}
int height(Tree<α> t)
{
return (t != null) ? 1 + max( height(t.left), height(t.right) )
: 0;
}
Let me briefly spell this out for you. We are defining…
a recursive type Tree<α> which represents a node in a binary tree. Each node stores a value of some type α and has references to optional left and right subtrees of the same type.
a function height which returns the furthest distance from any leaf node to the root node t.
Now, let's turn the above pseudo-code for height into proper Java syntax! (I'll keep on omitting some boilerplate for brevity's sake, such as object-orientation and accessibility modifiers.) I'm going to show two possible solutions.
1. Universal type solution:
The most obvious fix is to simply make height generic by introducing the type parameter α into its signature:
<α> int height(Tree<α> t)
{
return (t != null) ? 1 + max( height(t.left), height(t.right) )
: 0;
}
This would allow you to declare variables and create expressions of type α inside that function, if you wanted to. But...
2. Existential type solution:
If you look at our method's body, you will notice that we're not actually accessing, or working with, anything of type α! There are no expressions having that type, nor any variables declared with that type... so, why do we have to make height generic at all? Why can't we simply forget about α? As it turns out, we can:
int height(Tree<?> t)
{
return (t != null) ? 1 + max( height(t.left), height(t.right) )
: 0;
}
As I wrote at the very beginning of this answer, existential and universal types are complementary / dual in nature. Thus, if the universal type solution was to make height more generic, then we should expect that existential types have the opposite effect: making it less generic, namely by hiding/removing the type parameter α.
As a consequence, you can no longer refer to the type of t.value in this method nor manipulate any expressions of that type, because no identifier has been bound to it. (The ? wildcard is a special token, not an identifier that "captures" a type.) t.value has effectively become opaque; perhaps the only thing you can still do with it is type-cast it to Object.
Summary:
===========================================================
| universally existentially
| quantified type quantified type
---------------------+-------------------------------------
calling method |
needs to know | yes no
the type argument |
---------------------+-------------------------------------
called method |
can use / refer to | yes no
the type argument |
=====================+=====================================
These are all good examples, but I choose to answer it a little bit differently. Recall from math, that ∀x. P(x) means "for all x's, I can prove that P(x)". In other words, it is a kind of function, you give me an x and I have a method to prove it for you.
In type theory, we are not talking about proofs, but of types. So in this space we mean "for any type X you give me, I will give you a specific type P". Now, since we don't give P much information about X besides the fact that it is a type, P can't do much with it, but there are some examples. P can create the type of "all pairs of the same type": P<X> = Pair<X, X> = (X, X). Or we can create the option type: P<X> = Option<X> = X | Nil, where Nil is the type of the null pointers. We can make a list out of it: List<X> = (X, List<X>) | Nil. Notice that the last one is recursive, values of List<X> are either pairs where the first element is an X and the second element is a List<X> or else it is a null pointer.
Now, in math ∃x. P(x) means "I can prove that there is a particular x such that P(x) is true". There may be many such x's, but to prove it, one is enough. Another way to think of it is that there must exist a non-empty set of evidence-and-proof pairs {(x, P(x))}.
Translated to type theory: A type in the family ∃X.P<X> is a type X and a corresponding type P<X>. Notice that while before we gave X to P, (so that we knew everything about X but P very little) that the opposite is true now. P<X> doesn't promise to give any information about X, just that there there is one, and that it is indeed a type.
How is this useful? Well, P could be a type that has a way of exposing its internal type X. An example would be an object which hides the internal representation of its state X. Though we have no way of directly manipulating it, we can observe its effect by poking at P. There could be many implementations of this type, but you could use all of these types no matter which particular one was chosen.
To directly answer your question:
With the universal type, uses of T must include the type parameter X. For example T<String> or T<Integer>. For the existential type uses of T do not include that type parameter because it is unknown or irrelevant - just use T (or in Java T<?>).
Further information:
Universal/abstract types and existential types are a duality of perspective between the consumer/client of an object/function and the producer/implementation of it. When one side sees a universal type the other sees an existential type.
In Java you can define a generic class:
public class MyClass<T> {
// T is existential in here
T whatever;
public MyClass(T w) { this.whatever = w; }
public static MyClass<?> secretMessage() { return new MyClass("bazzlebleeb"); }
}
// T is universal from out here
MyClass<String> mc1 = new MyClass("foo");
MyClass<Integer> mc2 = new MyClass(123);
MyClass<?> mc3 = MyClass.secretMessage();
From the perspective of a client of MyClass, T is universal because you can substitute any type for T when you use that class and you must know the actual type of T whenever you use an instance of MyClass
From the perspective of instance methods in MyClass itself, T is existential because it doesn't know the real type of T
In Java, ? represents the existential type - thus when you are inside the class, T is basically ?. If you want to handle an instance of MyClass with T existential, you can declare MyClass<?> as in the secretMessage() example above.
Existential types are sometimes used to hide the implementation details of something, as discussed elsewhere. A Java version of this might look like:
public class ToDraw<T> {
T obj;
Function<Pair<T,Graphics>, Void> draw;
ToDraw(T obj, Function<Pair<T,Graphics>, Void>
static void draw(ToDraw<?> d, Graphics g) { d.draw.apply(new Pair(d.obj, g)); }
}
// Now you can put these in a list and draw them like so:
List<ToDraw<?>> drawList = ... ;
for(td in drawList) ToDraw.draw(td);
It's a bit tricky to capture this properly because I'm pretending to be in some sort of functional programming language, which Java isn't. But the point here is that you are capturing some sort of state plus a list of functions that operate on that state and you don't know the real type of the state part, but the functions do since they were matched up with that type already.
Now, in Java all non-final non-primitive types are partly existential. This may sound strange, but because a variable declared as Object could potentially be a subclass of Object instead, you cannot declare the specific type, only "this type or a subclass". And so, objects are represented as a bit of state plus a list of functions that operate on that state - exactly which function to call is determined at runtime by lookup. This is very much like the use of existential types above where you have an existential state part and a function that operates on that state.
In statically typed programming languages without subtyping and casts, existential types allow one to manage lists of differently typed objects. A list of T<Int> cannot contain a T<Long>. However, a list of T<?> can contain any variation of T, allowing one to put many different types of data into the list and convert them all to an int (or do whatever operations are provided inside the data structure) on demand.
One can pretty much always convert a record with an existential type into a record without using closures. A closure is existentially typed, too, in that the free variables it is closed over are hidden from the caller. Thus a language that supports closures but not existential types can allow you to make closures that share the same hidden state that you would have put into the existential part of an object.
An existential type is an opaque type.
Think of a file handle in Unix. You know its type is int, so you can easily forge it. You can, for instance, try to read from handle 43. If it so happens that the program has a file open with this particular handle, you'll read from it. Your code doesn't have to be malicious, just sloppy (e.g., the handle could be an uninitialized variable).
An existential type is hidden from your program. If fopen returned an existential type, all you could do with it is to use it with some library functions that accept this existential type. For instance, the following pseudo-code would compile:
let exfile = fopen("foo.txt"); // No type for exfile!
read(exfile, buf, size);
The interface "read" is declared as:
There exists a type T such that:
size_t read(T exfile, char* buf, size_t size);
The variable exfile is not an int, not a char*, not a struct File—nothing you can express in the type system. You can't declare a variable whose type is unknown and you cannot cast, say, a pointer into that unknown type. The language won't let you.
Seems I’m coming a bit late, but anyway, this document adds another view of what existential types are, although not specifically language-agnostic, it should be then fairly easier to understand existential types: http://www.cs.uu.nl/groups/ST/Projects/ehc/ehc-book.pdf (chapter 8)
The difference between a universally and existentially quantified type can be characterized by the following observation:
The use of a value with a ∀ quantified type determines the type to choose for the instantiation of the quantified type variable. For example, the caller of the identity function “id :: ∀a.a → a” determines the type to choose for the type variable a for this particular application of id. For the function application “id 3” this type equals Int.
The creation of a value with a ∃ quantified type determines, and hides, the type of the quantified type variable. For example, a creator of a “∃a.(a, a → Int)” may have constructed a value of that type from “(3, λx → x)”; another creator has constructed a value with the same type from “(’x’, λx → ord x)”. From a users point of view both values have the same type and are thus interchangeable. The value has a specific type chosen for type variable a, but we do not know which type, so this information can no longer be exploited. This value specific type information has been ‘forgotten’; we only know it exists.
A universal type exists for all values of the type parameter(s). An existential type exists only for values of the type parameter(s) that satisfy the constraints of the existential type.
For example in Scala one way to express an existential type is an abstract type which is constrained to some upper or lower bounds.
trait Existential {
type Parameter <: Interface
}
Equivalently a constrained universal type is an existential type as in the following example.
trait Existential[Parameter <: Interface]
Any use site can employ the Interface because any instantiable subtypes of Existential must define the type Parameter which must implement the Interface.
A degenerate case of an existential type in Scala is an abstract type which is never referred to and thus need not be defined by any subtype. This effectively has a shorthand notation of List[_] in Scala and List<?> in Java.
My answer was inspired by Martin Odersky's proposal to unify abstract and existential types. The accompanying slide aids understanding.
Research into abstract datatypes and information hiding brought existential types into programming languages. Making a datatype abstract hides info about that type, so a client of that type cannot abuse it. Say you've got a reference to an object... some languages allow you to cast that reference to a reference to bytes and do anything you want to that piece of memory. For purposes of guaranteeing behavior of a program, it's useful for a language to enforce that you only act on the reference to the object via the methods the designer of the object provides. You know the type exists, but nothing more.
See:
Abstract Types Have Existential Type, MITCHEL & PLOTKIN
http://theory.stanford.edu/~jcm/papers/mitch-plotkin-88.pdf
I created this diagram. I don't know if it's rigorous. But if it helps, I'm glad.
As I understand it's a math way to describe interfaces/abstract class.
As for T = ∃X { X a; int f(X); }
For C# it would translate to a generic abstract type:
abstract class MyType<T>{
private T a;
public abstract int f(T x);
}
"Existential" just means that there is some type that obey to the rules defined here.
What is the difference between
a parameter passed by reference
a parameter passed by value?
Could you give me some examples, please?
First and foremost, the "pass by value vs. pass by reference" distinction as defined in the CS theory is now obsolete because the technique originally defined as "pass by reference" has since fallen out of favor and is seldom used now.1
Newer languages2 tend to use a different (but similar) pair of techniques to achieve the same effects (see below) which is the primary source of confusion.
A secondary source of confusion is the fact that in "pass by reference", "reference" has a narrower meaning than the general term "reference" (because the phrase predates it).
Now, the authentic definition is:
When a parameter is passed by reference, the caller and the callee use the same variable for the parameter. If the callee modifies the parameter variable, the effect is visible to the caller's variable.
When a parameter is passed by value, the caller and callee have two independent variables with the same value. If the callee modifies the parameter variable, the effect is not visible to the caller.
Things to note in this definition are:
"Variable" here means the caller's (local or global) variable itself -- i.e. if I pass a local variable by reference and assign to it, I'll change the caller's variable itself, not e.g. whatever it is pointing to if it's a pointer.
This is now considered bad practice (as an implicit dependency). As such, virtually all newer languages are exclusively, or almost exclusively pass-by-value. Pass-by-reference is now chiefly used in the form of "output/inout arguments" in languages where a function cannot return more than one value.
The meaning of "reference" in "pass by reference". The difference with the general "reference" term is that this "reference" is temporary and implicit. What the callee basically gets is a "variable" that is somehow "the same" as the original one. How specifically this effect is achieved is irrelevant (e.g. the language may also expose some implementation details -- addresses, pointers, dereferencing -- this is all irrelevant; if the net effect is this, it's pass-by-reference).
Now, in modern languages, variables tend to be of "reference types" (another concept invented later than "pass by reference" and inspired by it), i.e. the actual object data is stored separately somewhere (usually, on the heap), and only "references" to it are ever held in variables and passed as parameters.3
Passing such a reference falls under pass-by-value because a variable's value is technically the reference itself, not the referred object. However, the net effect on the program can be the same as either pass-by-value or pass-by-reference:
If a reference is just taken from a caller's variable and passed as an argument, this has the same effect as pass-by-reference: if the referred object is mutated in the callee, the caller will see the change.
However, if a variable holding this reference is reassigned, it will stop pointing to that object, so any further operations on this variable will instead affect whatever it is pointing to now.
To have the same effect as pass-by-value, a copy of the object is made at some point. Options include:
The caller can just make a private copy before the call and give the callee a reference to that instead.
In some languages, some object types are "immutable": any operation on them that seems to alter the value actually creates a completely new object without affecting the original one. So, passing an object of such a type as an argument always has the effect of pass-by-value: a copy for the callee will be made automatically if and when it needs a change, and the caller's object will never be affected.
In functional languages, all objects are immutable.
As you may see, this pair of techniques is almost the same as those in the definition, only with a level of indirection: just replace "variable" with "referenced object".
There's no agreed-upon name for them, which leads to contorted explanations like "call by value where the value is a reference". In 1975, Barbara Liskov suggested the term "call-by-object-sharing" (or sometimes just "call-by-sharing") though it never quite caught on. Moreover, neither of these phrases draws a parallel with the original pair. No wonder the old terms ended up being reused in the absence of anything better, leading to confusion.4
(I would use the terms "new" or "indirect" pass-by-value/pass-by-reference for the new techniques.)
NOTE: For a long time, this answer used to say:
Say I want to share a web page with you. If I tell you the URL, I'm
passing by reference. You can use that URL to see the same web page I
can see. If that page is changed, we both see the changes. If you
delete the URL, all you're doing is destroying your reference to that
page - you're not deleting the actual page itself.
If I print out the page and give you the printout, I'm passing by
value. Your page is a disconnected copy of the original. You won't see
any subsequent changes, and any changes that you make (e.g. scribbling
on your printout) will not show up on the original page. If you
destroy the printout, you have actually destroyed your copy of the
object - but the original web page remains intact.
This is mostly correct except the narrower meaning of "reference" -- it being both temporary and implicit (it doesn't have to, but being explicit and/or persistent are additional features, not a part of the pass-by-reference semantic, as explained above). A closer analogy would be giving you a copy of a document vs inviting you to work on the original.
1Unless you are programming in Fortran or Visual Basic, it's not the default behavior, and in most languages in modern use, true call-by-reference is not even possible.
2A fair amount of older ones support it, too
3In several modern languages, all types are reference types. This approach was pioneered by the language CLU in 1975 and has since been adopted by many other languages, including Python and Ruby. And many more languages use a hybrid approach, where some types are "value types" and others are "reference types" -- among them are C#, Java, and JavaScript.
4There's nothing bad with recycling a fitting old term per se, but one has to somehow make it clear which meaning is used each time. Not doing that is exactly what keeps causing confusion.
It's a way how to pass arguments to functions. Passing by reference means the called functions' parameter will be the same as the callers' passed argument (not the value, but the identity - the variable itself). Pass by value means the called functions' parameter will be a copy of the callers' passed argument. The value will be the same, but the identity - the variable - is different. Thus changes to a parameter done by the called function in one case changes the argument passed and in the other case just changes the value of the parameter in the called function (which is only a copy). In a quick hurry:
Java only supports pass by value. Always copies arguments, even though when copying a reference to an object, the parameter in the called function will point to the same object and changes to that object will be see in the caller. Since this can be confusing, here is what Jon Skeet has to say about this.
C# supports pass by value and pass by reference (keyword ref used at caller and called function). Jon Skeet also has a nice explanation of this here.
C++ supports pass by value and pass by reference (reference parameter type used at called function). You will find an explanation of this below.
Codes
Since my language is C++, i will use that here
// passes a pointer (called reference in java) to an integer
void call_by_value(int *p) { // :1
p = NULL;
}
// passes an integer
void call_by_value(int p) { // :2
p = 42;
}
// passes an integer by reference
void call_by_reference(int & p) { // :3
p = 42;
}
// this is the java style of passing references. NULL is called "null" there.
void call_by_value_special(int *p) { // :4
*p = 10; // changes what p points to ("what p references" in java)
// only changes the value of the parameter, but *not* of
// the argument passed by the caller. thus it's pass-by-value:
p = NULL;
}
int main() {
int value = 10;
int * pointer = &value;
call_by_value(pointer); // :1
assert(pointer == &value); // pointer was copied
call_by_value(value); // :2
assert(value == 10); // value was copied
call_by_reference(value); // :3
assert(value == 42); // value was passed by reference
call_by_value_special(pointer); // :4
// pointer was copied but what pointer references was changed.
assert(value == 10 && pointer == &value);
}
And an example in Java won't hurt:
class Example {
int value = 0;
// similar to :4 case in the c++ example
static void accept_reference(Example e) { // :1
e.value++; // will change the referenced object
e = null; // will only change the parameter
}
// similar to the :2 case in the c++ example
static void accept_primitive(int v) { // :2
v++; // will only change the parameter
}
public static void main(String... args) {
int value = 0;
Example ref = new Example(); // reference
// note what we pass is the reference, not the object. we can't
// pass objects. The reference is copied (pass-by-value).
accept_reference(ref); // :1
assert ref != null && ref.value == 1;
// the primitive int variable is copied
accept_primitive(value); // :2
assert value == 0;
}
}
Wikipedia
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_value
http://en.wikipedia.org/wiki/Pass_by_reference#Call_by_reference
This guy pretty much nails it:
http://javadude.com/articles/passbyvalue.htm
Many answers here (and in particular the most highly upvoted answer) are factually incorrect, since they misunderstand what "call by reference" really means. Here's my attempt to set matters straight.
TL;DR
In simplest terms:
call by value means that you pass values as function arguments
call by reference means that you pass variables as function arguments
In metaphoric terms:
Call by value is where I write down something on a piece of paper and hand it to you. Maybe it's a URL, maybe it's a complete copy of War and Peace. No matter what it is, it's on a piece of paper which I've given to you, and so now it is effectively your piece of paper. You are now free to scribble on that piece of paper, or use that piece of paper to find something somewhere else and fiddle with it, whatever.
Call by reference is when I give you my notebook which has something written down in it. You may scribble in my notebook (maybe I want you to, maybe I don't), and afterwards I keep my notebook, with whatever scribbles you've put there. Also, if what either you or I wrote there is information about how to find something somewhere else, either you or I can go there and fiddle with that information.
What "call by value" and "call by reference" don't mean
Note that both of these concepts are completely independent and orthogonal from the concept of reference types (which in Java is all types that are subtypes of Object, and in C# all class types), or the concept of pointer types like in C (which are semantically equivalent to Java's "reference types", simply with different syntax).
The notion of reference type corresponds to a URL: it is both itself a piece of information, and it is a reference (a pointer, if you will) to other information. You can have many copies of a URL in different places, and they don't change what website they all link to; if the website is updated then every URL copy will still lead to the updated information. Conversely, changing the URL in any one place won't affect any other written copy of the URL.
Note that C++ has a notion of "references" (e.g. int&) that is not like Java and C#'s "reference types", but is like "call by reference". Java and C#'s "reference types", and all types in Python, are like what C and C++ call "pointer types" (e.g. int*).
OK, here's the longer and more formal explanation.
Terminology
To start with, I want to highlight some important bits of terminology, to help clarify my answer and to ensure we're all referring to the same ideas when we are using words. (In practice, I believe the vast majority of confusion about topics such as these stems from using words in ways that to not fully communicate the meaning that was intended.)
To start, here's an example in some C-like language of a function declaration:
void foo(int param) { // line 1
param += 1;
}
And here's an example of calling this function:
void bar() {
int arg = 1; // line 2
foo(arg); // line 3
}
Using this example, I want to define some important bits of terminology:
foo is a function declared on line 1 (Java insists on making all functions methods, but the concept is the same without loss of generality; C and C++ make a distinction between declaration and definition which I won't go into here)
param is a formal parameter to foo, also declared on line 1
arg is a variable, specifically a local variable of the function bar, declared and initialized on line 2
arg is also an argument to a specific invocation of foo on line 3
There are two very important sets of concepts to distinguish here. The first is value versus variable:
A value is the result of evaluating an expression in the language. For example, in the bar function above, after the line int arg = 1;, the expression arg has the value 1.
A variable is a container for values. A variable can be mutable (this is the default in most C-like languages), read-only (e.g. declared using Java's final or C#'s readonly) or deeply immutable (e.g. using C++'s const).
The other important pair of concepts to distinguish is parameter versus argument:
A parameter (also called a formal parameter) is a variable which must be supplied by the caller when calling a function.
An argument is a value that is supplied by the caller of a function to satisfy a specific formal parameter of that function
Call by value
In call by value, the function's formal parameters are variables that are newly created for the function invocation, and which are initialized with the values of their arguments.
This works exactly the same way that any other kinds of variables are initialized with values. For example:
int arg = 1;
int another_variable = arg;
Here arg and another_variable are completely independent variables -- their values can change independently of each other. However, at the point where another_variable is declared, it is initialized to hold the same value that arg holds -- which is 1.
Since they are independent variables, changes to another_variable do not affect arg:
int arg = 1;
int another_variable = arg;
another_variable = 2;
assert arg == 1; // true
assert another_variable == 2; // true
This is exactly the same as the relationship between arg and param in our example above, which I'll repeat here for symmetry:
void foo(int param) {
param += 1;
}
void bar() {
int arg = 1;
foo(arg);
}
It is exactly as if we had written the code this way:
// entering function "bar" here
int arg = 1;
// entering function "foo" here
int param = arg;
param += 1;
// exiting function "foo" here
// exiting function "bar" here
That is, the defining characteristic of what call by value means is that the callee (foo in this case) receives values as arguments, but has its own separate variables for those values from the variables of the caller (bar in this case).
Going back to my metaphor above, if I'm bar and you're foo, when I call you, I hand you a piece of paper with a value written on it. You call that piece of paper param. That value is a copy of the value I have written in my notebook (my local variables), in a variable I call arg.
(As an aside: depending on hardware and operating system, there are various calling conventions about how you call one function from another. The calling convention is like us deciding whether I write the value on a piece of my paper and then hand it to you, or if you have a piece of paper that I write it on, or if I write it on the wall in front of both of us. This is an interesting subject as well, but far beyond the scope of this already long answer.)
Call by reference
In call by reference, the function's formal parameters are simply new names for the same variables that the caller supplies as arguments.
Going back to our example above, it's equivalent to:
// entering function "bar" here
int arg = 1;
// entering function "foo" here
// aha! I note that "param" is just another name for "arg"
arg /* param */ += 1;
// exiting function "foo" here
// exiting function "bar" here
Since param is just another name for arg -- that is, they are the same variable, changes to param are reflected in arg. This is the fundamental way in which call by reference differs from call by value.
Very few languages support call by reference, but C++ can do it like this:
void foo(int& param) {
param += 1;
}
void bar() {
int arg = 1;
foo(arg);
}
In this case, param doesn't just have the same value as arg, it actually is arg (just by a different name) and so bar can observe that arg has been incremented.
Note that this is not how any of Java, JavaScript, C, Objective-C, Python, or nearly any other popular language today works. This means that those languages are not call by reference, they are call by value.
Addendum: call by object sharing
If what you have is call by value, but the actual value is a reference type or pointer type, then the "value" itself isn't very interesting (e.g. in C it's just an integer of a platform-specific size) -- what's interesting is what that value points to.
If what that reference type (that is, pointer) points to is mutable then an interesting effect is possible: you can modify the pointed-to value, and the caller can observe changes to the pointed-to value, even though the caller cannot observe changes to the pointer itself.
To borrow the analogy of the URL again, the fact that I gave you a copy of the URL to a website is not particularly interesting if the thing we both care about is the website, not the URL. The fact that you scribbling over your copy of the URL doesn't affect my copy of the URL isn't a thing we care about (and in fact, in languages like Java and Python the "URL", or reference type value, can't be modified at all, only the thing pointed to by it can).
Barbara Liskov, when she invented the CLU programming language (which had these semantics), realized that the existing terms "call by value" and "call by reference" weren't particularly useful for describing the semantics of this new language. So she invented a new term: call by object sharing.
When discussing languages that are technically call by value, but where common types in use are reference or pointer types (that is: nearly every modern imperative, object-oriented, or multi-paradigm programming language), I find it's a lot less confusing to simply avoid talking about call by value or call by reference. Stick to call by object sharing (or simply call by object) and nobody will be confused. :-)
Before understanding the two terms, you must understand the following. Every object has two things that can make it be distinguished.
Its value.
Its address.
So if you say employee.name = "John", know that there are two things about name. Its value which is "John" and also its location in the memory which is some hexadecimal number maybe like this: 0x7fd5d258dd00.
Depending on the language's architecture or the type (class, struct, etc.) of your object, you would be either transferring "John" or 0x7fd5d258dd00
Passing "John" is known as passing by value.
Passing 0x7fd5d258dd00 is known as passing by reference. Anyone who is pointing to this memory location will have access to the value of "John".
For more on this, I recommend you to read about dereferencing a pointer and also why choose struct (value type) over class (reference type).
Here is an example:
#include <iostream>
void by_val(int arg) { arg += 2; }
void by_ref(int&arg) { arg += 2; }
int main()
{
int x = 0;
by_val(x); std::cout << x << std::endl; // prints 0
by_ref(x); std::cout << x << std::endl; // prints 2
int y = 0;
by_ref(y); std::cout << y << std::endl; // prints 2
by_val(y); std::cout << y << std::endl; // prints 2
}
The simplest way to get this is on an Excel file. Let’s say for example that you have two numbers, 5 and 2 in cells A1 and B1 accordingly, and you want to find their sum in a third cell, let's say A2.
You can do this in two ways.
Either by passing their values to cell A2 by typing = 5 + 2 into this cell. In this case, if the values of the cells A1 or B1 change, the sum in A2 remains the same.
Or by passing the “references” of the cells A1 and B1 to cell A2 by typing = A1 + B1. In this case, if the values of the cells A1 or B1 change, the sum in A2 changes too.
When passing by reference you are basically passing a pointer to the variable. Pass by value you are passing a copy of the variable.
In basic usage this normally means pass by reference, changes to the variable will seen be in the calling method and in pass by value they won’t.
Pass by value sends a copy of the data stored in the variable you specify, and pass by reference sends a direct link to the variable itself.
So if you pass a variable by reference and then change the variable inside the block you passed it into, the original variable will be changed. If you simply pass by value, the original variable will not be able to be changed by the block you passed it into, but you will get a copy of whatever it contained at the time of the call.
Take a look at this photo:
In the first case (pass by reference), when the variable is set or changed inside the function, the external variable also changes.
But in the second case (pass by value), changing the variable inside the function doesn't have any effect on the external variable.
For reading the article, see this link.
Pass by value - The function copies the variable and works with a copy (so it doesn't change anything in the original variable)
Pass by reference - The function uses the original variable. If you change the variable in the other function, it changes in the original variable too.
Example (copy and use/try this yourself and see):
#include <iostream>
using namespace std;
void funct1(int a) // Pass-by-value
{
a = 6; // Now "a" is 6 only in funct1, but not in main or anywhere else
}
void funct2(int &a) // Pass-by-reference
{
a = 7; // Now "a" is 7 both in funct2, main and everywhere else it'll be used
}
int main()
{
int a = 5;
funct1(a);
cout << endl << "A is currently " << a << endl << endl; // Will output 5
funct2(a);
cout << endl << "A is currently " << a << endl << endl; // Will output 7
return 0;
}
Keep it simple, peeps. Walls of text can be a bad habit.
A major difference between them is that value-type variables store values, so specifying a value-type variable in a method call passes a copy of that variable's value to the method. Reference-type variables store references to objects, so specifying a reference-type variable as an argument passes the method a copy of the actual reference that refers to the object. Even though the reference itself is passed by value, the method can still use the reference it receives to interact with—and possibly modify—the original object. Similarly, when returning information from a method via a return statement, the method returns a copy of the value stored in a value-type variable or a copy of the reference stored in a reference-type variable. When a reference is returned, the calling method can use that reference to interact with the referenced object. So, in effect, objects are always passed by reference.
In c#, to pass a variable by reference so the called method can modify the variable's, C# provides keywords ref and out. Applying the ref keyword to a parameter declaration allows you to pass a variable to a method by reference—the called method will be able to modify the original variable in the caller. The ref keyword is used for variables that already have been initialized in the calling method. Normally, when a method call contains an uninitialized variable as an argument, the compiler generates an error. Preceding a parameter with keyword out creates an output parameter. This indicates to the compiler that the argument will be passed into the called method by reference and that the called method will assign a value to the original variable in the caller. If the method does not assign a value to the output parameter in every possible path of execution, the compiler generates an error. This also prevents the compiler from generating an error message for an uninitialized variable that is passed as an argument to a method. A method can return only one value to its caller via a return statement, but can return many values by specifying multiple output (ref and/or out) parameters.
see c# discussion and examples here link text
Examples:
class Dog
{
public:
barkAt( const std::string& pOtherDog ); // const reference
barkAt( std::string pOtherDog ); // value
};
const & is generally best. You don't incur the construction and destruction penalty. If the reference isn't const your interface is suggesting that it will change the passed in data.
If you don't want to change the value of the original variable after passing it into a function, the function should be constructed with a "pass by value" parameter.
Then the function will have only the value, but not the address of the passed in variable. Without the variable's address, the code inside the function cannot change the variable value as seen from the outside of the function.
But if you want to give the function the ability to change the value of the variable as seen from the outside, you need to use pass by reference. As both the value and the address (reference) are passed in and are available inside the function.
In short, Passed by value is WHAT it is and passed by reference is WHERE it is.
If your value is VAR1 = "Happy Guy!", you will only see "Happy Guy!". If VAR1 changes to "Happy Gal!", you won't know that. If it's passed by reference, and VAR1 changes, you will.
Pass by value means how to pass a value to a function by making use of arguments. In pass by value, we copy the data stored in the variable we specify, and it is slower than pass by reference because the data is copied.
Or we make changes in the copied data. The original data is not affected. And in pass by reference or pass by address, we send a direct link to the variable itself. Or passing a pointer to a variable. It is faster because less time is consumed.
Here is an example that demonstrates the differences between pass by value - pointer value - reference:
void swap_by_value(int a, int b){
int temp;
temp = a;
a = b;
b = temp;
}
void swap_by_pointer(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void swap_by_reference(int &a, int &b){
int temp;
temp = a;
a = b;
b = temp;
}
int main(void){
int arg1 = 1, arg2 = 2;
swap_by_value(arg1, arg2);
cout << arg1 << " " << arg2 << endl; //prints 1 2
swap_by_pointer(&arg1, &arg2);
cout << arg1 << " " << arg2 << endl; //prints 2 1
arg1 = 1; //reset values
arg2 = 2;
swap_by_reference(arg1, arg2);
cout << arg1 << " " << arg2 << endl; //prints 2 1
}
The “passing by reference” method has an important limitation. If a parameter is declared as passed by reference (so it is preceded by the & sign) its corresponding actual parameter must be a variable.
An actual parameter referring to “passed by value” formal parameter may be an expression in general, so it is allowed to use not only a variable but also a literal or even a function invocation's result.
The function is not able to place a value in something other than a variable. It cannot assign a new value to a literal or force an expression to change its result.
PS: You can also check Dylan Beattie answer in the current thread that explains it in plain words.
1. Pass By Value / Call By Value
void printvalue(int x)
{
x = x + 1 ;
cout << x ; // 6
}
int x = 5;
printvalue(x);
cout << x; // 5
In call by value, when you pass a value to printvalue(x) i.e. the argument which is 5, it is copied to void printvalue(int x). Now, we have two different values 5 and the copied value 5 and these two values are stored in different memory locations. So if you make any change inside void printvalue(int x) it won't reflect back to the argument.
2. Pass By Reference/ Call By Reference
void printvalue(int &x)
{
x = x + 1 ;
cout << x ; // 6
}
int x = 5;
printvalue(x);
cout << x; // 6
In call by reference, there's only one difference. We use & i.e. the address operator. By doing
void printvalue(int &x) we are referring to the address of x which tells us that it both refers to the same location. Hence, any changes made inside the function will reflect outside.
Now that you're here, you should also know about ...
3. Pass By Pointer/ Call By Address
void printvalue(int* x)
{
*x = *x + 1 ;
cout << *x ; // 6
}
int x = 5;
printvalue(&x);
cout << x; // 6
In pass by address, the pointer int* x holds the address passed to it printvalue(&x). Hence, any changes done inside the function will reflect outside.
The question is "vs".
And nobody has pointed to an important point. In passing with values, additional memory is occupied to store the passed variable values.
While in passing with a reference, no additional memory is occupied for the values (memory efficient in circumstances).