Parameter Parameter
Passing Passing
Giuseppe Attardi Giuseppe Attardi Università di Pisa Università di Pisa
Parameter Passing Modes Parameter Passing Modes
Call by valueCall by value
Call by referenceCall by reference
Call by result, value/resultCall by result, value/result
C++ referencesC++ references
Closures as parametersClosures as parameters
Call by nameCall by name
Label parametersLabel parameters
Variable number of argumentsVariable number of arguments
Function returnsFunction returns
Terminology Terminology
Expressions evaluate to R-values
Variables and components of
variables of structured types also have an L-value, that is, an address where their R-value is stored
The assignment statement requires an L-value on the left-hand side (L stands for “left”) and an R-value on the right-hand side (R stands for
“right”)
Examples of L-value, R-value Examples of L-value, R-value
int x = 3;
int x = 3;
x = x;
x = x;
int v[40];
int v[40];
v[3] = v[3]
v[3] = v[3]
(x == 3) = (x == 3) = 3 = 3 =
int foo();
int foo();
foo = ….
foo = ….
point.x = 12;
point.x = 12;
Value Model, Reference Value Model, Reference
Model Model
b = 2;
b = 2;
c = b; b = b +1;
c = b; b = b +1;
a = b + c;
a = b + c;
5 2 2 a
b c
a b c
Value model Reference
model 6
3 32
Example Example
class Point { int x, y; } class Point { int x, y; }
Point p = Point(3, 4);
Point p = Point(3, 4);
Point p2 = p;
Point p2 = p;
p.x = 5;
p.x = 5;
p2.x ? p2.x ?
foo(p);
foo(p);
int i = 3;
int i = 3;
Integer i = new Integer(3);
Integer i = new Integer(3);
C Language C Language
void foo (int* x) { void foo (int* x) {
*x = 3;
*x = 3;
}}
struct Point { int x, y};
struct Point { int x, y};
Point p;
Point p;
bar(&p);
bar(&p);
void bar(Point* p) { p->x = 3; } void bar(Point* p) { p->x = 3; }
Point* p = new Point(); p->x = 5;
Point* p = new Point(); p->x = 5;
Point* p2 = p;
Point* p2 = p;
bar(p2);
bar(p2);
void bar(Point p1) { p1.x = 3; } void bar(Point p1) { p1.x = 3; } Point p = new Point(); p.x = 5;
Point p = new Point(); p.x = 5;
bar(p);
bar(p);
p.x?p.x?
Reference Model Reference Model
In language using the Reference In language using the Reference Model, every variable is an L-value Model, every variable is an L-value
When it appears in a R-value context, When it appears in a R-value context, it must be
it must be dereferenceddereferenced
Usually dereference is implicitUsually dereference is implicit
Examples:Examples:
– Algol68, Lisp, ML, Haskell, SmallTalk
Java: mixed (value for built-in types)Java: mixed (value for built-in types)
Call by value Call by value
The value of the R-valueThe value of the R-value of the actual of the actual parameter is
parameter is copiedcopied into the formal into the formal parameter at invocation
parameter at invocation
Java has
Java has only only call by value call by value
Java is strictly pass-by-value.Java is strictly pass-by-value.
See the Java Language Specification:
See the Java Language Specification:
http://java.sun.com/docs/books/jls/third_edition http://java.sun.com/docs/books/jls/third_edition
/html/classes.html#8.4.1:
/html/classes.html#8.4.1:
When the method or constructor is invoked (15.12), the values of the actual argument expressions
initialize newly created parameter variables, each of the declared Type, before execution of the body of the method or constructor. The Identifier that
appears in the DeclaratorId may be used as a simple name in the body of the method or constructor to refer to the formal parameter.
Object references are passed by value.Object references are passed by value.
Call by result Call by result
The value of the formal parameter is The value of the formal parameter is copied into the actual parameter
copied into the actual parameter (which must have an L-value) at (which must have an L-value) at
procedure return.
procedure return.
Call by value/result Call by value/result
The parameter is treated as in value The parameter is treated as in value mode during invocation and as in mode during invocation and as in
result mode during return.
result mode during return.
Note Note
foo (inout x) { … x …}
foo (inout x) { … x …}
foo1 (ref x) { … x = x + 1; … } foo1 (ref x) { … x = x + 1; … }
foo1(v[3]);
foo1(v[3]);
s = “asdasd”;
s = “asdasd”;
foo1(s); // OK foo1(s); // OK
foo1(“asdasd”); // KO foo1(“asdasd”); // KO
foo1(3); // KO foo1(3); // KO
int y = 7;
int y = 7;
foo1(y);
foo1(y);
y?y?
Note Note
foo2 (Point ref q) { q.x = 7; q = null; } foo2 (Point ref q) { q.x = 7; q = null; }
Point p = new Point(3,4);
Point p = new Point(3,4);
Point prev = p;
Point prev = p;
foo2(ref p);
foo2(ref p);
p == prev?
p == prev?
Note Note
void foo (ref int x) { void foo (ref int x) {
x = x + 3;
x = x + 3;
x = x/0;
x = x/0;
} }
int z = 2;
int z = 2;
foo(z);
foo(z);
Call by reference Call by reference
The L-valueThe L-value of the formal parameter of the formal parameter is set to the L-value is set to the L-value of the actual of the actual
parameter.
parameter.
The address of the formal parameter The address of the formal parameter is the same as the address of the
is the same as the address of the actual parameter.
actual parameter.
Any assignment to the formal Any assignment to the formal parameter
parameter immediatelyimmediately affects the affects the actual parameter.
actual parameter.
Note Note
// C#
// C#
void foo(int ref x) { x += 1; } void foo(int ref x) { x += 1; }
// C++
// C++
void foo(int& x) { x += 1; } void foo(int& x) { x += 1; }
int a[3];
int a[3];
a[0] = 0;
a[0] = 0;
foo(ref a[0]);
foo(ref a[0]); // C#// C#
foo(a[0]);
foo(a[0]); // C++// C++
foo(p);
foo(p);
C++ Reference Datatype C++ Reference Datatype
C++ provides a Reference dataypeC++ provides a Reference dataype, built from other , built from other types
types
If T is a type T& is a new type called “reference to T”If T is a type T& is a new type called “reference to T”
One should avoid the confusion between the general One should avoid the confusion between the general concept of
concept of referencereference and a Reference Type and a Reference Type
Also avoid the confusion with the notion of Reference Also avoid the confusion with the notion of Reference types
types in Java and C# in Java and C#
Reference Types are not pointersReference Types are not pointers, even though they are , even though they are implemented through pointers and hence accessing a implemented through pointers and hence accessing a
reference type may involve an implicit dereference reference type may involve an implicit dereference
operation operation
Using Reference Types in parameters provides access Using Reference Types in parameters provides access to arguments even though they are still passed by value to arguments even though they are still passed by value
Reference/Value Types Reference/Value Types
In programming language theory, a In programming language theory, a reference type
reference type is a data type is a data type that can that can only be accessed by references
only be accessed by references
Objects of a reference type are Objects of a reference type are always dynamically allocated always dynamically allocated
value type objects instead can be value type objects instead can be
manipulated directly and are copied manipulated directly and are copied
when moved (assignment, parameter when moved (assignment, parameter
passing or function return) passing or function return)
C++ Reference Type C++ Reference Type
Example Example
void foo(int& x) { void foo(int& x) {
int& z = x;
int& z = x;
x = x + 1;
x = x + 1;
}}
int y = 7;
int y = 7;
foo(y);
foo(y);
y ?y ?
foo(3);
foo(3); // only feasible if x was// only feasible if x was // declared as const int&
// declared as const int&
Call by name Call by name
Every use of the formal parameter causes Every use of the formal parameter causes
the actual parameter to be freshly the actual parameter to be freshly
evaluated in the referencing environment evaluated in the referencing environment
of the invocation point.
of the invocation point.
If the formal parameter’s L-value is needed If the formal parameter’s L-value is needed
(for example, the parameter appears on (for example, the parameter appears on
the left-hand side of an assignment), the the left-hand side of an assignment), the
actual parameter’s L-value must be freshly actual parameter’s L-value must be freshly
evaluated.
evaluated.
If the formal parameter’s Rvalue is needed, If the formal parameter’s Rvalue is needed,
the actual parameter’s R-value must be the actual parameter’s R-value must be
freshly evaluated.
freshly evaluated.
Call by name: example Call by name: example
int sum(name int expr, name int j, int size) int sum(name int expr, name int j, int size) {{
int tot = 0;int tot = 0;
for (j = 0; j < size; j++)for (j = 0; j < size; j++) tot += expr;
tot += expr;
return tot;return tot;
}}
sum(A[i], i, n); /* sum of vector elements */
sum(A[i], i, n); /* sum of vector elements */
Note Note
{ int i;
{ int i;
int[] A;
int[] A;
&int thunk() { return &A[i]; }&int thunk() { return &A[i]; } sum(thunk, i, n);
sum(thunk, i, n);
}}
Call by macro Call by macro
Every use of the formal parameter Every use of the formal parameter causes the text of the actual
causes the text of the actual
parameter to be freshly evaluated in parameter to be freshly evaluated in
the referencing environment of the the referencing environment of the
use point.
use point.
Macro Example Macro Example
#DEFINE foo(x) x + x
#DEFINE foo(x) x + x foo(read())
foo(read())
read() + read() read() + read()
inline int foo(int x) { return x + x; } inline int foo(int x) { return x + x; }
int foo(int& x, int &y) { x++; y++; return x + y;}
int foo(int& x, int &y) { x++; y++; return x + y;}
Foo(a, a);
Foo(a, a);
Parameter passing modes Parameter passing modes
Implementation
Implementation OperationsOperations Change to Change to actual?
actual? Alias?Alias?
Value
Value ValueValue RWRW NoNo nono
In, const
In, const Value, Value, reference
reference RORO NoNo MaybeMaybe Out (C#, Ada)
Out (C#, Ada) Value, Value, reference
reference WOWO YesYes MaybeMaybe Value/result
Value/result ValueValue RWRW YesYes NoNo Var, ref
Var, ref ReferenceReference RWRW YesYes YesYes Sharing
Sharing Value, Value, reference
reference RWRW YesYes MaybeMaybe In out
In out Value, Value, reference
reference RWRW YesYes MaybeMaybe NameName ClosureClosure RWRW YesYes yesyes
Exercise Exercise
swap(x, y) using just call-by-valueswap(x, y) using just call-by-value void swap(int x, int y) {
void swap(int x, int y) { int temp;int temp;
temp = x;temp = x;
x = y;x = y;
y = temp;y = temp;
};};
Does not work.
Does not work.
Swap by call by name Swap by call by name
swap(x, y) using just call-by-nameswap(x, y) using just call-by-name int b[10]; swap(i, b[i]);
int b[10]; swap(i, b[i]);
void swap(name int x, name int y) { void swap(name int x, name int y) { int temp;int temp;
temp = x;temp = x;
x = y;x = y;
y = temp;y = temp;
};};
Swap with C# ref Swap with C# ref
void swap(int ref x, int ref y) { void swap(int ref x, int ref y) {
int tmp = y;
y = x;
x = tmp;
}
int a = 3, b =5;
swap(a, b);
Note on Note on
List l = new List();
List l = new List();
Student s = new Student();
Student s = new Student();
l.add(s);
l.add(s);
float pi = 3.14;
float pi = 3.14;
l.add(pi);
l.add(pi);
(new Integer(314)).toString();
(new Integer(314)).toString();
s.toString();
s.toString();
Note Note
int a[] = new int[3];
int a[] = new int[3];
int b[] = new int[5];
int b[] = new int[5];
swap(a, b);
swap(a, b);
aa
swap(i, a[i]);
swap(i, a[i]);
int temp; temp = x; x = y; y = temp;
int temp; temp = x; x = y; y = temp;
a=3, b=5; a=5, b=5; a=5, b=3;
a=3, b=5; a=5, b=5; a=5, b=3;
void swap(inout int x, inout int y) { void swap(inout int x, inout int y) { int temp;int temp;
temp = x;temp = x;
x = y;x = y;
y = temp;y = temp;
};};
Exercise Exercise
swap(x, y) using just call-by-nameswap(x, y) using just call-by-name
swap(name x, name y) => { swap(name x, name y) => { }}
Does it work?
Does it work?
Call by name Call by name
Counter example:
Counter example:
swap(i, A[i]) swap(i, A[i])
(i=3, A[3] = 4) => (i=4, A[4] = 4, A[3]
(i=3, A[3] = 4) => (i=4, A[4] = 4, A[3]
unchanged) unchanged)
Call by value/result Call by value/result
swap(i, A[i])swap(i, A[i])
works even in case (i=2, A[2]= 99) works even in case (i=2, A[2]= 99)
Call by value Call by value
Copies argumentCopies argument
Special cases:Special cases:
– array – struct
typedef struct { int x, y} Pair;
Pair q;
zed(q);
Pair foo() { Pair p; return p; } Pair p = foo();
stack.push_back(Pair(2,3));
int [200000] v;
bar(v);
std::string s; bad(s);
int* foo() { int* foo() {
int v[100];
int v[100];
return v;
return v;
}}