confused with functions and passing by pointer, references, and value.

in my attempt to self-learn c++ with a technical book (sams teach yourself c++) i have gotten stumped on a particular code in a lesson. i have learned how to pass values, pointers, and references to functions in a certain syntactical way that i understand. i want to quickly show what i expect;

//*********************passing by value*************************

void swap(int x, int y); //function prototype and perameter that accepts integers

void swap (int x, int y) //function definition
{
//do something
}

int main()
{
int x = 5, y = 10;

swap(x,y); // passing the integers by value to the function

//*************************passing by pointer refernce*********************

void swap(int *x, int *y); //function prototype and perameter that accepts pointers

void swap (int *px, int *py) //function definition
{
//do something
}

int main()
{
int x = 5, y = 10;

swap(&x,&y); // passing the pointer with the required address-of-operator to the function

//***********************passing be reference****************************

void swap(int &x, int &y); //function prototype and perameter that accepts references

void swap (int &rx, int &ry) //function definition
{
//do something
}

int main()
{
int x = 5, y = 10;

swap(x,y); //passing by reference to function. passing by reference is syntactically as easy as passing by value and is the reason chosen over passing by pointer.

//***********************************************************************

now, the book has thrown a curve at me and i have spent some time to understand but am having trouble. please consider the following code below from the book and explain to me why it is passing a pointer to a function that expects a value, a pointer to a function that expects a syntactically easy reference, and why it does not pass with the address-of-operator (&) to the function expecting a pointer?




//Listing 11.10 - Data slicing with passing by value
#include <iostream>
using namespace std;

class Mammal
{
public:
Mammal():itsAge(1) { }
virtual ~Mammal() { }
virtual void Speak() const { cout << "Mammal speak!\n"; }

protected:
int itsAge;
};

class Dog : public Mammal
{
public:
void Speak()const { cout << "Woof!\n"; }
};

class Cat : public Mammal
{
public:
void Speak()const { cout << "Meow!\n"; }
};

void ValueFunction (Mammal); //prototype expecting a value
void PtrFunction (Mammal*); //prototype expecting a pointer
void RefFunction (Mammal&); // prototype expecting a reference
int main()
{
Mammal* ptr=0;
int choice;
while (1)
{
bool fQuit = false;
cout << "(1)dog (2)cat (0)Quit: ";
cin >> choice;
switch (choice)
{
case 0: fQuit = true;
break;
case 1: ptr = new Dog;
break;
case 2: ptr = new Cat;
break;
default: ptr = new Mammal;
break;
}
if (fQuit == true)
break;
PtrFunction(ptr); //passing to pointer function but where is the "&"?
RefFunction(*ptr); //passing to reference function but why the "*"?
ValueFunction(*ptr); //passing by value but why passing a pointer?
}
return 0;
}

void ValueFunction (Mammal MammalValue)
{
MammalValue.Speak();
}

void PtrFunction (Mammal * pMammal)
{
pMammal->Speak(); //the member select operator i have not fully understood
}

void RefFunction (Mammal & rMammal)
{
rMammal.Speak();
}
When using variables:

&foo gives you a pointer to foo.
*foo "dereferences" foo (gives you whatever foo points to). foo must be a pointer.

Quick example:

1
2
3
4
5
6
int* ptr;
int val = 0;

ptr = &val;  // we are taking a pointer to val and assigning it to foo
*ptr = 5;  // this assigns 5 to whatever ptr points to.  In this case
   //  since ptr points to val, this is the same as saying "val = 5;" 


Now passing to functions is the same idea. The thing that's tripping you up is that 'ptr' already is a pointer:

 
PtrFunction(ptr); //passing to pointer function but where is the "&"? 


There's no & here because 'ptr' already is a pointer. If we were to say '&ptr' we would be giving it a pointer to a pointer to a Mammal (Mammal**), and not a pointer to a Mammal (Mammal*).

1
2
RefFunction(*ptr); //passing to reference function but why the "*"?
ValueFunction(*ptr); //passing by value but why passing a pointer? 


Ref and Val syntax is the same.
Here, you use *ptr because ptr is a pointer. In order to get the value that the pointer points to, we need to put that * in there.


pMammal->Speak(); //the member select operator i have not fully understood

The -> operator is the same as the . operator except it works on pointers.

foo.bar takes an object foo and gets its bar member.
foo->bar takes a pointer to an object foo and gets its bar member.

foo->bar is really just shorter way to say (*foo).bar
thanks for the reply.

i have some questions;

&foo gives you a pointer to foo.

ptr = &val; // we are taking a pointer to val and assigning it to foo


in your quotes above; does the variable with the address-of-operator preceding it (&foo) give the pointer or does the does the definition of a pointer variable (int * pPointer) give the pointer? i guess i should ask what gives and what takes the pointer.

the -> member select operator now makes more sense, thanks.

i also wanted to originally ask is why the reason to declare a pointer function? for example, int * someFunction (int * someVariable1, int * someVariable2). why have a function return a pointer when it can just return a normal integer since the function is being passed pointers to manipulate multiple data members?
in your quotes above; does the variable with the address-of-operator preceding it (&foo) give the pointer or does the does the definition of a pointer variable (int * pPointer) give the pointer?


I guess that was a little unclear/confusing. Sorry about that. ^^

It's a little weird with pointers. When you are declaring the type, then you use * to indicate the type of a pointer.

However, in expressions, the & operator gives you a pointer (whereas * actually does the opposite and dereferences the pointer -- confusing, I know)

So.. in simple terms, let's break this into two parts.

Simple integer:
1
2
3
4
5
int val;  // here we're declaring a variable.  That variable is of type 'int'
  // 'int' here is our type

val = 5;  // in this expression, '5' is a literal of type int.  val is also an int.
  //  so we are assigning one int to another. 


Pointers are the same:
1
2
3
4
5
6
int* ptr;  // here we're declaring a variable.  That varialbe is of type 'int*'
  // 'int*' here is our type (pointer to an int)

ptr = &val;  // in this expression, 'val' is an int, therefore '&val' is an int*
  // and of course, ptr is an int*
  // so we are assigning one int* to another 



why have a function return a pointer when it can just return a normal integer since the function is being passed pointers to manipulate multiple data members?


Some common reasons for returning pointers have to do with polymorphism, and/or returning newly allocated memory. But those are more advances things that I wouldn't worry about yet.

For the kind of examples you're working with now -- there isn't much point in returning pointers.
1
2
3
4
5
6
7
8
9
10
void swap (int x, int y) //function definition
{
//do something
}

int main()
{
int x = 5, y = 10;

swap(x,y); // passing the integers by value to the function 


your function definition should always be under the main function and the prototype above the main function.
this gives easier to read code (easier to understand, a standard if you will).
Identifiers are always just identifiers and you can even change the name of reserved keywords
(also identifiers themselves); this is created through enumerations.
Last edited on
your function definition should always be under the main function and the prototype above the main function.
this gives easier to read code (easier to understand, a standard if you will).


That's not true at all. If the code is a quick one-liner like that, creating a separate prototype is just extra, unnecessary code.
Topic archived. No new replies allowed.