760 likes | 954 Views
References, Pointers and Memory. References vs. Pointers, Addresses, Pointer Arithmetic, Pointers & Arrays, Stack & Heap memory. Learning & Development Team. http://academy.telerik.com. Telerik Software Academy. Table of Contents. References and their Applications Pointers and Memory
E N D
References, Pointers and Memory References vs. Pointers, Addresses, Pointer Arithmetic, Pointers & Arrays, Stack & Heap memory Learning & Development Team http://academy.telerik.com Telerik Software Academy
Table of Contents • References and their Applications • Pointers and Memory • Working with Pointers • Referencing & Dereferencing • Pointer arithmetic • Pointers vs. References • Pointers and Arrays • C++ Memory and Storage Types • Working with Dynamic and Static Memory
References Variables aliases, Passing references to functions
References • A variable indicates a chunk of memory • Computer perceives the variable as that chunk • References are aliases of variables • Same type, same memory, different name • i.e., indicate same chunk of memory as the variable • A reference only represents one variable • Through its lifetime • Must be initialized immediately (on declaration)
References '&' denotes a reference Initialization is obligatory • Syntax for defining a reference to a variable • Reference points to same memory as its variable: • Its value is the value of the variable • Assigning the reference a value will actually assign the variable a value int v = 5; int &r = v; cout<<r<<endl; //prints 5 v = 6; cout<<r<<endl; //prints 6 r = 4; cout<<v<<endl; //prints 4 cout<<r<<endl; //prints 4 int &r = someVar; //reference to variable named //someVar (already existing)
Reference Basics Live Demo
Usage of References • References are most used with functions • Enable the function to change parameters • Remove overhead from "sending" parameters intSomeFunction(int ¶meterByReference, ...) { //... }
Usage of References • Reference parameters to edit values • The function accesses the variable, not its copy • Variable passed in call to function is affected void MakePositive(int &number) { if(number < 0) { //this affects the variable in the caller number = -number; } } int main() { int a = -5; MakePositive(a); //after this line, a is 5 }
Usage of References • References to avoid overhead • Normal parameters are copied • Copying large objects can take too much time • Especially when this happens often • Almost no good reason to copy parameters • Any operation done on a copy can be done on a reference – with the same effect (when reading) • Sending by reference doesn't copy the object, just its reference (which is fast)
Usage of References • Example of fast and slow way of sending parameters to a function • Note: this is valid for potentially large objects (a vector can have many elements). Sending primitive types (int, char…) by copy and by reference is almost the same in speed intGetSum(vector<int> &nums) //fast – only reference is sent { int sum = 0 int size = nums.size(); for(inti=0; i<size; i++) { sum += nums[i]; } return sum; } intGetSum(vector<int> nums) //overhead – elements copied { int sum = 0 int size = nums.size(); for(inti=0; i<size; i++) { sum += nums[i]; } return sum; }
Usage of References • Reference parameters can be a problem • OK to send reference instead of the whole data • But does the function read or edit the data? • You can't be sure, especially if you're using 3rd party code • const references solve this problem
Usage of References • const references • Work the same way, but data can only be read • A normal reference can be assigned to a const one • A const reference cannot be assigned to a normal one • i.e. a function cannot make a writeable reference from a const one intGetSum(const vector<int> &nums) {//this function can't edit nums int sum = 0 int size = nums.size(); for(inti=0; i<size; i++) { sum += nums[i]; } return sum; }
Using References Live Demo
Pointers and Memory Representing data in bytes, Variable addresses, Stack and Dynamic Memory
Memory • Computers work on data, stored in variables • Variables a program has at a given time are in the Random Access Memory (RAM) • RAM is just an array of bytes (software POV) • Each byte in RAM has an address (e.g. 0x000013A1) • Its index in the array, usually as a hex number • Information is described by address and value • of the byte(s) at that address
Memory • Early computing days • Programming was moving and editing bytes • From one address to another • No "abstract" operations such as +, -, *, / • The programmer writes everything from scratch • Today, low-level memory is handled through: • Data types • Predefined operations (often on hardware level) • E.g. assigning values is copying memory
Variables in Memory • Most data types occupy more than one byte • Occupied bytes are sequential • E.g. data for a 4-byte int starting at 0x000013A3, also occupies 0x000013A4, 0x000013A5 and 0x000013A6 • Address of a variable • The address of its first byte • The program can access the next bytes • By knowing the size of the data type
Variables in Memory • Example of a 4-byte integer in memory at address 0x13A3, with a value of 624 • in a Big-endian system • i.e. most-significant byte is leftmost address int x = 624; cout<<&x<<endl; //outputs 0x13A3 //(in the described case) //&x reads as "the address of x" //not the same as referencevariables, //returns address of the first byte of x intx = 624;
Memory Pointers • Pointer – special variable, associated with an address in memory • Holds the memory address of another variable • "Points" to another variable • Can point to any byte in memory • Special "null" (0) value – shows the pointer currently holds no variable's address • Two essential operations for using pointers • Referencing • Dereferencing
Memory Pointers • Referencing – getting a variable's address • Variable's address (as a number) is returned • from the variable's identifier • i.e. gets the value of a pointer to the variable intx = 624; Here, referencing x gives 0x13A3 (5027 decimal) Let p be a pointer to x Then, the value of p is 0x13A3 (5027 in decimal)
Memory Pointers • Dereferencing – getting value from an address • The variable (the memory data) is returned • from a pointer to that variable • i.e. accesses memory at the address, pointed by the pointer * Note: we need to know the data type to dereference p is a pointer to address 0x13A3 Let us dereference p as a 4-byte integer* x The data for x is in bytes 0x13A3 to 0x13A6 Then the value of x is 624
Pointers and Memory • Pointers – the common way to access memory • Most programming languages use pointers • Some allow full access (like C and C++) • Some hide pointers objects (C#, JS) • Reference and Dereference operators respectively create and evaluate pointers • Usually pointers can be incremented/decremented • i.e. "moved" to neighboring addresses
Working with Pointers in C++ The & and * operators, Pointer values and arithmetic, const pointers, Building pointers from addresses
Working with Pointers in C++ • C++ provides lots of functionality for working with pointers • Assigning pointers to variables and dereferencing • Pointer types – int, char, string, etc. • Basic memory pointers – a.k.a. void pointers • Assigning pointers to arbitrary memory addresses • Incrementing/Decrementing pointers • Casting pointers from one type to another
Pointers in C++ – Creating • Declaring and assigning pointers • C++ pointers have types and are declared as normal variables • A * (asterisk) sign prefix of the variable namedenotes a pointer • Typically, assigning values requires a variable's address – which is returned by the & operator int v = 5; int *vPtr; vPtr = &v; //get the address (pointer to) v cout<<vPtr<<endl; //prints hex address of v
Pointers in C++ – Dereferencing • Getting values from pointers • C++ pointers have types • Dereferencing accesses memory as • Dereferencing is done through the * (asterisk) operator, as a prefix to an existing pointer • This gives direct read/write access to the memory • Note: * is used for declaration and dereferencing int v = 5; int *vPtr= &v; //here, * means create a pointer (*vPtr)++; //here, * means access the pointed memory cout<<*vPtr<<endl; //prints 6
Pointer Basics Live Demo
Pointer Arithmetics • Arithmetic operations on pointers • "Move" a pointer to a neighboring memory cell • Addresses are just numbers • Moving from one address to the next means incrementing/decrementing the pointer • Allowed arithmetic operations on pointers • Addition • Subtraction • i.e. move a pointer 1, 2, 3, etc… positions
Pointer Arithmetics • Pointer arithmetics work in different ways • For different pointer types • E.g. incrementing int* and char* usually works differently • Increment/Decrement depend on data type • More precisely, the size of the data type • Incrementing a pointer of type T by 1 means incrementing the address to which it points to by 1 multiplied by sizeof(T) • Decrementing is analogous
Pointer Arithmetics • Example of pointer arithmetics • Suppose the current system uses 1 byte for char, 2 bytes for short and 4 bytes for int char *charPtr = ...//memory address 0x13A0 short *shortPtr = ...//memory address 0x14A0 int *intPtr = ...//memory address 0x15A0 charPtr++; shortPtr++; intPtr++; cout<<charPtr<<", "<<shortPtr<<", "<<intPtr<<endl; //prints 0x13A1, 0x14A2, 0x15A4
Pointer Arithmetics • Example explanation 0x13A0 + sizeof(char) charPtr is 0x13A0, sizeof(char) is 1, 0x13A0 + 1 = 0x13A1 shortPtr is 0x14A0, sizeof(short) is 2, 0x14A0 + 2 = 0x14A2 intPtr is 0x15A0, sizeof(int) is 4, 0x15A0 + 4 = 0x15A4 charPtr 0x14A0 + sizeof(short) shortPtr 0x15A0 + sizeof(int) intPtr
Pointer Arithmetics Live Demo
Pointer Arithmetics • A pointer can be incremented/decremented with any value (not just using ++ and --) • The expression p = p + 3 is valid • Where p is a pointer • Same rule for increasing by a multiple of type size is enforced • E.g. if p is an int pointer to address 0x15A0 • after the expression is evaluated p points 0x15AC • The same rules apply for subtraction
Pointers and const • As with references, • values pointed by pointers can be marked const • Unlike references, • pointers can change to what they point • Two pointer characteristics that can be const • Meaning a total of 4 pointer variations
Pointers and const • Non-constantpointerto non-constantvariable • Pointed memory can be modified by pointer • Pointed address can be changed • This is the "normal" pointer, from previous examples int x = 5; int *xPtr = &x; xPtr++; xPtr--; (*xPtr) = 4; int *otherXPtr = xPtr; //all operations valid
Pointers and const • Non-constantpointerto constantvariable • Pointed memory cannot be modified by pointer • Pointed address can be changed int x = 5; const int *xPtr = &x; xPtr++; xPtr--; (*xPtr) = 4; //error: read-only memory int *otherXPtr = xPtr; //error: invalid conversion
Pointers and const • Constantpointerto non-constantvariable • Pointed memory can be modified by pointer • Pointed address cannot be changed int x = 5; int * const xPtr = &x; xPtr++; //error: read-only pointer xPtr--; //error: read-only pointer (*xPtr) = 4; int *otherXPtr = xPtr; cout<<x<<endl;
Pointers and const • Constantpointerto constantvariable • Pointed memory cannot be modified by pointer • Pointed address cannot be changed int x = 5; const int * const xPtr = &x; xPtr++; ///error: read-only pointer xPtr--; ///error: read-only pointer (*xPtr) = 4; ///error: read-only memory int *otherXPtr = xPtr; ///error: invalid conversion cout<<x<<endl;
Pointers and const • Pointers are useful as function parameters • Non-const pointers to non-const variables • Passing data to the function for modification • Traversing and modifying memory (arrays) • Non-const pointers to const variables • Efficiently passing large data to a function • Protecting the data from modification • Much like constreferences, so most compilers implement const references this way
Pointers and const • const pointers in general • Useful for storing specific memory locations • And using them directly, i.e. no casting • Especially when working with: • Hardware expecting input at a specific address (i.e. you use const pointer to non-const memory) • Hardware producing output at a specific address (i.e. you use const pointer to const memory)
Pointers and const Live Demo
Pointers to Pointers in C++ • Pointers are just numbers and have addresses • So you can have pointers to pointers • Each pointer "level" is called an indirection • E.g., a pointer to a pointer is a double indirection • At declaration, one * per each indirection char x = 'a'; char * xPtr = &x; char ** xPtrPtr = &xPtr; x * xPtr ** xPtrPtr
Pointers to Pointers in C++ • Pointers to pointers have many applications • Multidimensional arrays, composite objects, … • Modifying pointer address by functions • i.e. modify where the pointer points, not the data void MovePtrToNextZero(int ** pointerAddress) { int value = **pointerAddress; while(value != 0) { (*pointerAddress)++; value = **pointerAddress; } } //Note: an often better (not always applicable) approach //is to return a new pointer, not modify the parameter
Pointers to Pointers Live Demo
Pointer to Specific Memory • C++ allows creating pointers to specific memory addresses • E.g. you can make a pointer point to 0x13A0 • Regardless of whether or not the program is allowed to access that memory • Accessing the memory could trigger an access violation (error code 0xC0000005) • Avoid creating pointers in such a way • Very unsafe and error-prone • Necessary in some cases (low-level code)
Pointer to Specific Memory • Initialize pointer to specific memory address • Simply provide the address as a number • Hex is the convention, but not obligatory • And cast it to the desired pointer type • Some argue cast should be reinterpret_cast • reinterpret_castforces cast (regardless of type) • Also sort of says "Here be dragons!" int *ptr = (int*)5024; int *otherPtr = reinterpret_cast<int*>(0x13A0); cout << (ptr==otherPtr) << endl; //prints 1 cout << ptr << endl; //prints 0x13A0
Pointers in C++ – Void Pointers • Void pointers are a special type of pointer • Not associated with a data type • Can point to any variable/byte of memory • Useful as a "universal pointer" • Cannot do pointer arithmetic • Cannot modify memory or be dereferenced • Void pointers are useful after casted int a = 5; char b = 'x'; void *p; p = &a; p = &b; cout << *((char*)p) << endl; //prints 'x'
C++ Function Pointers • Function pointers are special pointers • Similar restrictions as void pointers • Typically used to pass functions as parameters • Declaration and calling are similar to normal function declaration and calling • With brackets around function name • * before function name, inside the brackets #include <cmath> ... double (*squareRootPtr)(double) = sqrt; cout << (*squareRootPtr)(9) << endl; //prints 3
Function Pointers Live Demo
Pointers vs. References Main Differences, Advantages and Disadvantages