670 likes | 882 Views
Aliasing. Joe Meehean. Aliasing. An alias is another name for the same object two variables names are attached to the same data Aliasing is really important in C++ and many other programming languages well see why when we cover Objects C++ does aliasing in two ways references pointers.
E N D
Aliasing Joe Meehean
Aliasing • An alias is another name for the same object • two variables names are attached to the same data • Aliasing is really important in C++ • and many other programming languages • well see why when we cover Objects • C++ does aliasing in two ways • references • pointers
References • References are aliases that “refer” to other variables • its just another name for an object • Compound type • type defined in terms of another type • e.g., arrays are compound types • Reference is a compound type • type &variable; • e.g., int &foo; • should be read from right to left:“foo is a reference to an int”
References • Initializing a reference • References must be initialized at declaration • Must be initialized using object of the same type • cannot be initialized using a literal • After initialization a reference is forever bound to that object • cannot rebind to another object intval = 7; int &refVal = val; // GOOD int &refVal2; // ERROR int &refVal3 = 11; // ERROR double dval = 2.1; int &refVal3 = dval; // ERROR
References • All operations on a reference are performed on the underlying object 7 val intval = 7; int &refVal = val; refVal 9 val refVal = 9; refVal 10 val val++; refVal
References • References to constants • cannot change the underlying data • can refer to a const object or even literals • created using const keyword constintval = 7; constint &refVal = val; // GOOD int &refVal2 = val; // ERROR constint &refVal3 = 11; // GOOD constint &refVal4 = 12 * 57 + 1; // GOOD
References • As parameters of a function • nonreference parameters are copied using the corresponding function arguments • the original arguments cannot be changed 7 arg1 int arg1 = 7; int arg2 = 15; swap(arg1, arg2); void swap(int parm1, int parm2) { inttmp = parm1; parm1 = parm2; parm2 = tmp; } 15 arg2
References • As parameters of a function • nonreference parameters are copied using the corresponding function arguments • the original arguments cannot be changed 7 arg1 int arg1 = 7; int arg2 = 15; swap(arg1, arg2); void swap(int parm1, int parm2) { inttmp = parm1; parm1 = parm2; parm2 = tmp; } 15 arg2 7 parm1 15 parm2
References • As parameters of a function • nonreference parameters are copied using the corresponding function arguments • the original arguments cannot be changed 7 arg1 int arg1 = 7; int arg2 = 15; swap(arg1, arg2); void swap(int parm1, int parm2) { inttmp = parm1; parm1 = parm2; parm2 = tmp; } 15 arg2 7 15 parm1 15 7 parm2
References • As parameters of a function • nonreference parameters are copied using the corresponding function arguments • the original arguments cannot be changed 7 arg1 int arg1 = 7; int arg2 = 15; swap(arg1, arg2); void swap(int parm1, int parm2) { inttmp = parm1; parm1 = parm2; parm2 = tmp; } 15 arg2
References • As parameters of a function • reference parameters only copy the reference,not the actual data • binds parameters to argument’s data 7 arg1 int arg1 = 7; int arg2 = 15; swap(arg1, arg2); void swap(int& parm1,int& parm2) { inttmp = parm1; parm1 = parm2; parm2 = tmp; } 15 arg2
References • As parameters of a function • reference parameters only copy the reference,not the actual data • binds parameters to argument’s data parm1 7 arg1 int arg1 = 7; int arg2 = 15; swap(arg1, arg2); void swap(int& parm1,int& parm2) { inttmp = parm1; parm1 = parm2; parm2 = tmp; } 15 arg2 parm2
References • As parameters of a function • reference parameters only copy the reference,not the actual data • binds parameters to argument’s data parm1 7 15 arg1 int arg1 = 7; int arg2 = 15; swap(arg1, arg2); void swap(int& parm1,int& parm2) { inttmp = parm1; parm1 = parm2; parm2 = tmp; } 15 7 arg2 parm2
References • As parameters of a function • reference parameters only copy the reference,not the actual data • binds parameters to argument’s data 7 15 arg1 int arg1 = 7; int arg2 = 15; swap(arg1, arg2); void swap(int& parm1,int& parm2) { inttmp = parm1; parm1 = parm2; parm2 = tmp; } 15 7 arg2
References • Passing references avoids expensive copies • Adds new problems that data may be changed • maybe we want to be sure it won’t be • or want to use literals without copying • Pass const references boolisNegative(int& parm1) { return (parm1 < 0 ); } intval = -7; isNegative(val); // OK isNegative(-15); // WON’T COMPILE
References • Passing references avoids expensive copies • Adds new problems that data may be changed • maybe we want to be sure it won’t be • or want to use literals without copying • Pass const references boolisNegative(constint& parm1) { return (parm1 < 0 ); } intval = -7; isNegative(val); // OK isNegative(-15); // OK
References • Returning nonreferences • the return value (object) is copied • e.g., add 1 to absolute value -4 arg intarg = -4; abs(arg)++; cout << arg << endl; int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; }
References • Returning nonreferences • the return value (object) is copied • e.g., add 1 to absolute value -4 arg intarg = -4; abs(arg)++; cout << arg << endl; int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; } parm
References • Returning nonreferences • the return value (object) is copied • e.g., add 1 to absolute value -4 4 arg intarg = -4; abs(arg)++; cout << arg << endl; int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; } parm
References • Returning nonreferences • the return value (object) is copied • e.g., add 1 to absolute value -4 4 arg intarg = -4; abs(arg)++; cout << arg << endl; int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; } 4 tmp
References • Returning nonreferences • the return value (object) is copied • e.g., add 1 to absolute value -4 4 arg intarg = -4; abs(arg)++; cout << arg << endl; int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; } 4 5 tmp
References • Returning nonreferences • the return value (object) is copied • e.g., add 1 to absolute value 4 arg intarg = -4; abs(arg)++; cout << arg << endl; int abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; }
References • Returning a reference • the object itself is returned • returned reference can be assigned new data or updated -4 arg intarg = -4; abs(arg)++; cout << arg << endl; int& abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; } parm
References • Returning a reference • the object itself is returned • returned reference can be assigned new data or updated -4 4 arg intarg = -4; abs(arg)++; cout << arg << endl; int& abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; } parm
References • Returning a reference • the object itself is returned • returned reference can be assigned new data or updated -4 4 arg intarg = -4; abs(arg)++; cout << arg << endl; int& abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; } tmp
References • Returning a reference • the object itself is returned • returned reference can be assigned new data or updated 4 5 arg intarg = -4; abs(arg)++; cout << arg << endl; int& abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; } tmp
References • Returning a reference • the object itself is returned • returned reference can be assigned new data or updated 5 arg intarg = -4; abs(arg)++; cout << arg << endl; int& abs(int& parm){ if( parm < 0 ){ parm = parm * -1; } return parm; }
References • Returning a reference • never return a reference a local object int arg1 = 2; int arg2 = 5; int sum = add(arg1, arg2); int& add( int& parm1, int& parm2){ intval = parm1 + parm2; return val; } 2 arg1 5 arg2
References • Returning a reference • never return a reference a local object parm1 int arg1 = 2; int arg2 = 5; int sum = add(arg1, arg2); int& add( int& parm1, int& parm2){ intval = parm1 + parm2; return val; } 2 arg1 5 arg2 parm2
References • Returning a reference • never return a reference a local object parm2 int arg1 = 2; int arg2 = 5; int sum = add(arg1, arg2); int& add( int& parm1, int& parm2){ intval = parm1 + parm2; return val; } 2 arg1 5 arg2 parm2 7 val
References • Returning a reference • never return a reference a local object int arg1 = 2; int arg2 = 5; int sum = add(arg1, arg2); int& add( int& parm1, int& parm2){ intval = parm1 + parm2; return val; } 2 arg1 5 arg2 7 val tmp
References • Returning a reference • never return a reference a local object int arg1 = 2; int arg2 = 5; int sum = add(arg1, arg2); int& add( int& parm1, int& parm2){ intval = parm1 + parm2; return val; } 2 arg1 5 arg2 7 val sum
Pointers • Pointers are aliases that “point” to other variables • its just another name for an object • Pointer is a compound type • type *variable; • e.g., int*foo; • should be read from right to left:“foo is a pointer to an int”
Pointers • Alternate (dangerous) way to define pointers • type* variable; • e.g., int* foo; • dangerous: int* pval1, pval2; • pval1 is a pointer to an int • pval2 is an int • properly: int *pval1, *pval2;
Pointers • Pointers store the address of the object they alias • this gives us lots of power • more power than references • also more rope • We need to be able to get the address of objects • use the address-of operator & • e.g., the integer pointer pval is assigned the address of valintval = 7;int *pval = &val; • can use & on any value that can be on the left-side of an assignment • called lvalues • e.g., variables but not literals
Pointers • Valid pointers can have 3 possible values • address of a specific object • one address past the end of a specific object • 0 (or NULL) • Initializing pointers • pointers do not need to be bound to an object immediately • not valid until initialized to 1 of 3 values above • Legal assignments to (initialization of) pointers • constant expression with a value of 0 • address of an object with the correct type • one address past the end of an object • another valid pointer of the same type
Pointers 21 intaval = 21; int *pval1 = &aval; aval pval1
Pointers 21 intaval = 21; int *pval1 = &aval; aval pval1
Pointers 21 intaval = 21; int *pval1 = &aval; intbval = 5; int *pval2 = &bval; aval pval1 5 bval pval2
Pointers 21 intaval = 21; int *pval1 = &aval; intbval = 5; int *pval2 = &bval; pval1 = pval2; aval pval1 5 bval pval2
Pointers • Uninitialized pointers • have some address made up from garbage • whatever was in that memory before • using them is dangerous, may overwrite other objects memory • like a wild card pointer • DO NOT LEAVE POINTERS LAYING AROUND UNINITIALIZED
Pointers • Getting access to the object • not automatic like references • need to use the * operator • e.g.,intval = 8;int *pval = &val;cout << *pval << endl; • Dereferencing a pointer returns the object (an lval) • can assign new data to object • or modify object
Pointers 21 intaval = 21; int *pval1 = &aval; aval pval1
Pointers 21 5 intaval = 21; int *pval1 = &aval; *pval1 = 5; aval pval1
Pointers 5 6 intaval = 21; int *pval1 = &aval; *pval1 = 5; (*pval1)++; aval pval1
Pointers • We can also have pointers to pointers • a pointer stores an address of an object • a pointer is an object and also has an address(different from the one it stores) • just add another * in the initialization to make a pointer to a pointer • dereferencing a pointer to a pointer, yields the pointer • must dereference twice (**) to get to the object
Pointers 21 intaval = 21; int *pval1 = &aval; int **ppval = &pval1; intbval = 5; int *pval2 = &bval; aval pval1 ppval 5 bval pval2
Pointers 21 intaval = 21; int *pval1 = &aval; int **ppval = &pval1; intbval = 5; int *pval2 = &bval; ppval = &pval2; aval pval1 ppval 5 bval pval2
Pointers 21 intaval = 21; int *pval1 = &aval; int **ppval = &pval1; intbval = 5; int *pval2 = &bval; ppval = &pval2; **ppval = 8; aval pval1 ppval 5 8 bval pval2