Would someone please explain these constructs, hopefully with specific definitions and perhaps some online references. |
Since you said you're new to C++ and in the previous post you said your limited understanding, I'm assuming you do not full comprehend pointers and references.
A
pointer contains the address of an object in memory.
A
reference is the same thing, although the way you access the pointed to object in memory are different and their declarations are different.
1 2 3 4 5 6
|
char obj1 = 'a';
char obj2= 'b';
char* p = &obj1; // pointer
// Note the & before obj, that is the address of operator,
// should not be confused with the declaration of a reference
char& ref = obj; // reference
|
To access and change the value of an object using a pointer you have to dereference it:
|
*p = 'w'; // obj1 and ref is now 'w'
|
You can change the what the pointer is pointing to some other object:
1 2
|
// Note there is not * before p = ...
p = &obj2; // p now points to obj2, it contains obj2's address
|
To access the value of a reference you just do:
|
ref = 't'; // obj1 now equals 't'
|
But with references you cannot make it refer (or point) to another object.
The
sizeof()
a pointer and a reference is smaller than the
sizeof()
the object it holds, because all it contains is an address. That means you can call a function and pass it's arguments by value instead of by copy. Imagine you have a
std::vector<int>
with 100 000 elements, it would be very inefficient to pass it to a function by copy.
The advantage of using references is it makes it easier to read and write code. Compare the following to functions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
void f1(const std::vector<int>& arg_ref)
{
for(int i = 0; i < arg_ref.size(); ++i)
{
std::cout << arg_ref[i] << '\n';
}
}
void f2(const std::vector<int>* arg_ref)
{
for(int i = 0; i < *arg_ref.size(); ++i)
{
std::cout << *arg_ref[i] << '\n';
}
}
|
So how do you chose between pass by value, pass by reference, and pass by pointer? First of all there is no need to pass by pointer since it is the same thing as passing by reference.
The general rule of thumb is:
1). Use pass by value for small objects
2). Use pass by const reference when you don't need to modify what your passing, when the object is too big and it is inefficient to copy it.
3). Use pass by reference when you want to modify the object.
Why should avoid pass by reference and prefer pass by value:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
int incremet1(int arg)
{
return ++arg;
}
void increment2(int& arg)
{
++arg;
}
int main()
{
int x = 0;
increment1(x); // no harm done x is still 0
increment2(x); // x now equals 1
// anyone reading this will not see that x has been modified
x = increment1(x); // x now equals 2
// anyone reading this will see that we are modifying x
}
|
I usually pass by const value, it is better than const reference, because you can remove the const qualifier using
const_cast<>
. Removing the const from a pass by value won't do any harm to the object the caller passed, but removing the const from a pass by reference object can do a whole lot of harm to the unsuspecting caller.
When choosing how you want to pass an argument, have in mind that modern computers are really powerful. You shouldn't be worried about efficiency. People that worry about efficiency too much usually write messy and error-prone code, messy code is hard to understand and difficult to maintain.
So what your probably thinking now is, "So if pointers and references are kinda the same thing, why not use a reference, because it's easier to read and write code?" Pointers are used to implement data structures such as
std::vector
(which is a dynamic array), binary search trees, linked lists, and for allocating memory on the free store, but don't worry about that for now.
Word of advice: Never return a reference to a local variable in a function. Since the object was destroyed at the end of the function you are returning an address that does not contain a valid object and it is possible another program or the operating system might be using that address now.
The most confusing thing about pointers and references is there syntax, it's very similar, which makes it easy to get confused. Pointers and references were maybe the most difficult thing for in my early days. It is confusing for you now, but it will all become clear at some point.