- pointer
- A pointer refers directly to (or "points to") another value stored elsewhere in the computer memory using its address. It can be also interpreted as a pointer to many objects, depending on the semantics of the usage.
- reference
- Is a pointer with some (useful) restrictions and a reliefs. It's value can be set only once (at declaration) and it can point only to one object. The relief is that you don't have to apply any syntax for dereferencing. Another benefit is that you know that the area pointed by a reference does not have to be freed by you.
Pointer examples
int array[10]; // Array with 10 elements allocated on the stack
*array = 5; // Set the zeroth element to 5
*(array+1) = 6; // Set the first element to 6
array[2] = 7; // Set the second element to 7
int *array2 = new int[10]; // Array allocated on the heap
*array2 = 5; // Set the zeroth element to 5
*(array2+1) = 6; // Set the first element to 6
array2[2] = 7; // Set the second element to 7
delete[] array2; // Freeing allocation
int *p = array+3; // Create a pointer to the 3rd element
*p = 8; // Set it to 8
char s1[] = {'H','E','L','L','O','!',0}; // Char array on stack (terminated by zero)
char s2[] = "HELLO!"; // Char array on stack (terminated by zero)
const char *s3 = "HELLO!"; // Pointer to string literal. "const" because you do not want to change a literal, do you?
- In the first case you don't really have a pointer that is stored anywhere. Handling of aggregated arrays (on stack or in a class/struct) is presented with pointer-syntax.
- In the second case you really have a pointer on the stack that points to the allocated area which is on the heap.
To demonstrate the difference between pointers and pseudo pointers:
++array; // Will not compile
++array2; // Will incrase the array2 pointer by one
// (it will point to the 1st element in the array - not the 0th)
Note that you still have to call delete[] with a pointer that points to the 0th element!!! Something like
delete[] (array2-1);
Reference examples
Reference typed parameter
std::string ReverseText(const std::string& text)
{
size_t len = text.size();
std::string ret(len,'\0');
for(int i=0; i<len; ++i)
{
ret.at(i) = text.at(len-1-i);
}
return ret; // We love "named return value optimization"
}
Note: ret.at(i) returns a reference to the i-th character of the string.
- The parameter's value is not copied, just a pointer to it.
- You don't have to use pointer syntax like (*text).size() (or text->size()), you can use text.size() conveniently
- You don't have to test for NULL pointer. The user of the function can clearly see that he cannot pass a NULL pointer, that he/she must provide this parameter.
Invocation:
std::string s("Heavy Metal music");
std::cout << ReverseText(s) << std::endl;
Aliasing
A real life example would involve more complex concepts than the aliasing itself. It is rarely used, but very useful when needed. So let's see a l'art pour l'art teaching example!
unsigned int LargestCommonDivider(unsigned int a, unsigned int b)
{
while(a!=b)
{
unsigned int &greater(a>b?a:b);
unsigned int &smaller(a>b?b:a);
greater -= smaller;
}
return a;
}
- Let's see the usefulness and necessity of "functional programming minded" operator ?: here!
- The a and b variables are copies of the parameters given at the place of invocation, they can be used as ordinary local variables (which they are in reality).
See also
initializer list.
No comments:
Post a Comment