References or pointers?

D

desktop

I have made this example:

#include<iostream>

class Beer {
public:
Beer() {
std::cout << "made a beer\n";
num = 1;
}

Beer(int n) : num(n) {}

int getBeer(){
return num;
}

void remove(){
num--;
}

private:
int num;
};

class Brew {
public:
/* Simple*/
void drinkBeer(Beer b) {
std::cout << "Drank " << b.getBeer() << " instances of beers!\n";
b.remove();
}

void checkBeer(Beer b) {
std::cout << b.getBeer() << " instances of beers left!\n";
}




/* With references. Notice that the '&' is placed AFTER the type like the
* pointer operator. */
void drinkBeerRef(Beer& b) {
std::cout << "Drank " << b.getBeer() << " reference beers!\n";
b.remove();
}

void checkBeerRef(Beer& b) {
std::cout << b.getBeer() << " reference beers left!\n";
}



/* With pointers */
void drinkBeer(Beer* b) {
std::cout << "Drank " << b->getBeer() << " pointer beers!\n";
b->remove();
}

void checkBeer(Beer* b) {
std::cout << b->getBeer() << " pointer beers left!\n";
}
};


int main(){

/* (0) Calling default constructor. */
Beer b1;

/* (1) Make a brewery where you can drink! checkBeer will not print
* the right value. */
Beer b2(10); // make 10 beers.
Brew brew;
brew.drinkBeer(b2);
brew.checkBeer(b2);

std::cout << std::endl;


/* (2) Using references */
Beer b3(10); // make 10 beers.
brew.drinkBeerRef(b3);
brew.checkBeerRef(b3);

std::cout << std::endl;

/* (3) Using pointers */

/* Single object containing 10 beers. */
Beer* b4 = new Beer(10);

/* or:
*
* Beer* b4 = new Beer[10];
*
* using default constructor. 10 objects containing 1 beer.
*
* */

brew.drinkBeer(b4);
brew.checkBeer(b4);

return 0;
}


How does passing an argument as a reference differ from passing it as a
pointer (besides from also giving the right result)?

When you use 'new' the data is allocated on the heap and when changed in
a function will remain changed after the functions returns. But this is
also the case with references...does 'Beer b3' allocate 'b3' on the heap?
 
C

Carlo Capelli

desktop said:
I have made this example: ....
How does passing an argument as a reference differ from passing it as a
pointer (besides from also giving the right result)?

You can think to references as 'syntax sugar' for const pointers (beware,
not pointer to consts).
Passing an argument by reference is a safer and more convenient way to pass
the pointer to the value.
The callee can modify the value but not the pointer, i.e. can't switch the
'pointer' to something else.
When you use 'new' the data is allocated on the heap and when changed in a
function will remain changed after the functions returns. But this is also
the case with references...does 'Beer b3' allocate 'b3' on the heap?

b3 is on the stack, but the pertinent point is that the section marked /*
Simple*/ it's incorrect.
You pass 'by value' the beer, and that make sense only in the checkBeer
call.

Bye Carlo
 
T

terminator

I have made this example:

#include<iostream>

class Beer {
public:
Beer() {
std::cout << "made a beer\n";
num = 1;
}

Beer(int n) : num(n) {}

int getBeer(){
return num;
}

void remove(){
num--;
}

private:
int num;

};

class Brew {
public:
/* Simple*/
void drinkBeer(Beer b) {
std::cout << "Drank " << b.getBeer() << " instances of beers!\n";
b.remove();
}

void checkBeer(Beer b) {
std::cout << b.getBeer() << " instances of beers left!\n";
}

/* With references. Notice that the '&' is placed AFTER the type like the
* pointer operator. */
void drinkBeerRef(Beer& b) {
std::cout << "Drank " << b.getBeer() << " reference beers!\n";
b.remove();
}

void checkBeerRef(Beer& b) {
std::cout << b.getBeer() << " reference beers left!\n";
}

/* With pointers */
void drinkBeer(Beer* b) {
std::cout << "Drank " << b->getBeer() << " pointer beers!\n";
b->remove();
}

void checkBeer(Beer* b) {
std::cout << b->getBeer() << " pointer beers left!\n";
}

};

int main(){

/* (0) Calling default constructor. */
Beer b1;

/* (1) Make a brewery where you can drink! checkBeer will not print
* the right value. */
Beer b2(10); // make 10 beers.
Brew brew;
brew.drinkBeer(b2);
brew.checkBeer(b2);

**NO NO NO**
the 2 later lines are syntax errors.You must use the address-of
operator (&) to extract the address of an object and pass it to a
pointer:

brew.drinkBeer(&b2);
brew.checkBeer(&b2);
std::cout << std::endl;

/* (2) Using references */
Beer b3(10); // make 10 beers.
brew.drinkBeerRef(b3);
brew.checkBeerRef(b3);

std::cout << std::endl;

/* (3) Using pointers */

/* Single object containing 10 beers. */
Beer* b4 = new Beer(10);

/* or:
*
* Beer* b4 = new Beer[10];
*
* using default constructor. 10 objects containing 1 beer.
*
* */

brew.drinkBeer(b4);
brew.checkBeer(b4);
you can dereference a pointer via the derefrence operator(unary *).try
this one too:

brew.drinkBeerRef( * b4 );
brew.checkBeerRef( * b4 );

beware: you need to get rid of dynamic objects(created via new/new[]
operators) before ending the program :

delete b4;
/* or:
*
* delete[] b4;Beer* b4 = new Beer[10];
*
* if Beer* b4 = new Beer[10];
*
*/
return 0;
}

How does passing an argument as a reference differ from passing it as a
pointer (besides from also giving the right result)?

When you use 'new' the data is allocated on the heap and when changed in
a function will remain changed after the functions returns. But this is
also the case with references...does 'Beer b3' allocate 'b3' on the heap?

No,'b3' is allocated on the stack and deallocated(first destructed
then deallocated) prior to exiting the enclosing code block(main
function in this context).

Tip:
Dynamic objects (created with new ) are placed on the heap and live
there unless you do kill them (destroy with delete).
None - static objects declared in code blocks are destroyed when the
enclosing block exits.
Instance data members are destroyed by the owner object.
static objects are destroyed at the end of the program.
pointers can be inc/decremented(++/--) like integral types.this is
usefull when working with intrinsic arrays:

int a[10];
int * ptr =a;//ptr = & a[0];
cout <<*++ptr;//ptr= & a[1];cout<<*ptr;

regards,
FM.
 
D

desktop

terminator said:
**NO NO NO**
the 2 later lines are syntax errors.You must use the address-of
operator (&) to extract the address of an object and pass it to a
pointer:

Well I don't see why its syntactical incorrect. In Brew I have a method
that takes as argument a static object of type Beer.

I use the above lines to illustrate what happens if you DON'T use a
pointer or reference to Beer. The changes made will not be correct after
returning since the remove() call works on a copy of the passed object
and not the actual object.

To achieve the latter its necessary to pass the object as reference or
pointer.


brew.drinkBeer(&b2);
brew.checkBeer(&b2);
std::cout << std::endl;

/* (2) Using references */
Beer b3(10); // make 10 beers.
brew.drinkBeerRef(b3);
brew.checkBeerRef(b3);

std::cout << std::endl;

/* (3) Using pointers */

/* Single object containing 10 beers. */
Beer* b4 = new Beer(10);

/* or:
*
* Beer* b4 = new Beer[10];
*
* using default constructor. 10 objects containing 1 beer.
*
* */

brew.drinkBeer(b4);
brew.checkBeer(b4);
you can dereference a pointer via the derefrence operator(unary *).try
this one too:

brew.drinkBeerRef( * b4 );
brew.checkBeerRef( * b4 );

beware: you need to get rid of dynamic objects(created via new/new[]
operators) before ending the program :

delete b4;
/* or:
*
* delete[] b4;Beer* b4 = new Beer[10];
*
* if Beer* b4 = new Beer[10];
*
*/
return 0;
}

How does passing an argument as a reference differ from passing it as a
pointer (besides from also giving the right result)?

When you use 'new' the data is allocated on the heap and when changed in
a function will remain changed after the functions returns. But this is
also the case with references...does 'Beer b3' allocate 'b3' on the heap?

No,'b3' is allocated on the stack and deallocated(first destructed
then deallocated) prior to exiting the enclosing code block(main
function in this context).

Tip:
Dynamic objects (created with new ) are placed on the heap and live
there unless you do kill them (destroy with delete).
None - static objects declared in code blocks are destroyed when the
enclosing block exits.
Instance data members are destroyed by the owner object.
static objects are destroyed at the end of the program.
pointers can be inc/decremented(++/--) like integral types.this is
usefull when working with intrinsic arrays:


But a method that takes a reference to a static object will leave the
object changed after returning.
 
D

desktop

Carlo said:
You can think to references as 'syntax sugar' for const pointers (beware,
not pointer to consts).
Passing an argument by reference is a safer and more convenient way to pass
the pointer to the value.
The callee can modify the value but not the pointer, i.e. can't switch the
'pointer' to something else.


Ok thats a very good explanation, thanks!

b3 is on the stack, but the pertinent point is that the section marked /*
Simple*/ it's incorrect.
You pass 'by value' the beer, and that make sense only in the checkBeer
call.

I know but the example is also made to show what happens if you DON'T
pass an object as pointer or reference.
 
T

terminator

**NO NO NO**
the 2 later lines are syntax errors.You must use the address-of
operator (&) to extract the address of an object and pass it to a
pointer:

Well I don't see why its syntactical incorrect. In Brew I have a method
that takes as argument a static object of type Beer.

I use the above lines to illustrate what happens if you DON'T use a
pointer or reference to Beer. The changes made will not be correct after
returning since the remove() call works on a copy of the passed object
and not the actual object.

To achieve the latter its necessary to pass the object as reference or
pointer.






brew.drinkBeer(&b2);
brew.checkBeer(&b2);
std::cout << std::endl;
/* (2) Using references */
Beer b3(10); // make 10 beers.
brew.drinkBeerRef(b3);
brew.checkBeerRef(b3);
std::cout << std::endl;
/* (3) Using pointers */
/* Single object containing 10 beers. */
Beer* b4 = new Beer(10);
/* or:
*
* Beer* b4 = new Beer[10];
*
* using default constructor. 10 objects containing 1 beer.
*
* */
brew.drinkBeer(b4);
brew.checkBeer(b4);
you can dereference a pointer via the derefrence operator(unary *).try
this one too:
brew.drinkBeerRef( * b4 );
brew.checkBeerRef( * b4 );
beware: you need to get rid of dynamic objects(created via new/new[]
operators) before ending the program :
delete b4;
/* or:
*
* delete[] b4;Beer* b4 = new Beer[10];
*
* if Beer* b4 = new Beer[10];
*
*/
return 0;
}
How does passing an argument as a reference differ from passing it as a
pointer (besides from also giving the right result)?
When you use 'new' the data is allocated on the heap and when changed in
a function will remain changed after the functions returns. But this is
also the case with references...does 'Beer b3' allocate 'b3' on the heap?
No,'b3' is allocated on the stack and deallocated(first destructed
then deallocated) prior to exiting the enclosing code block(main
function in this context).
Tip:
Dynamic objects (created with new ) are placed on the heap and live
there unless you do kill them (destroy with delete).
None - static objects declared in code blocks are destroyed when the
enclosing block exits.
Instance data members are destroyed by the owner object.
static objects are destroyed at the end of the program.
pointers can be inc/decremented(++/--) like integral types.this is
usefull when working with intrinsic arrays:

But a method that takes a reference to a static object will leave the
object changed after returning.- Hide quoted text -

pointers and refrences are both used for passing by reference but they
obey different symantics and have different syntaxes you can not
initialize a pointer with a normal variable or vice-versa:

class A{};
A a1
A * Aptr=a1;//error
A a2=Aptr;//error
A & Aref1=Aptr;//error

you must write:

A * Aptr= & a1;//pass the address of 'a1' to 'Aptr'
A a2= * Aptr ;//pass the value pointed by 'Aptr' to 'a2'
A & Aref1= a1;//make 'Aref1' an aliase(new name)for 'a1'
A & Aref2= *Aptr;//make 'Aref2' a reference to what 'Aptr' points to

you seem not to know the meaning of 'static';read your book before
asking any more Qs.

FM.
 
C

Chris Thomasson

SasQ said:
Not always true.
The compiler is able to "inline" access by reference
so that it access the original value directly.

I was thinking in the sense that a reference wraps an underlying constant
pointer which points directly at the object.
 
J

Joe Greer

I was thinking in the sense that a reference wraps an underlying
constant pointer which points directly at the object.

In many cases, references are to objects as typedefs are to types. What
I mean is that a reference adds an alias to an existing object. What
lies under the covers can vary quite a bit. For example:

int f( object const & obj)
{
// In this form, obj most often is a hidden pointer, but with
// inlining a such, that may not be true either
}


int a;
int & b = a;

In the above form, most compilers won't have any backing for b at all
and will generate code as if you had just used 'a'. What adds to the
confusion is that in Java or C# they use references as pointers. That
is:

Object a = new Object;

a = new Object;

Works fine with the assignment changing the object that a points to and
the first object is lost to the garbage collector. In C++ If you wrote:

Object & a = *new Object;
a = *new Object;

You would have created a second new object and copied its contents on
top of the first object, then orphaned the second. That is, you can't
reseat references in C++. If you wanted the Jave/C# behavior, then you
would use pointers. That is what they are for. C++ doesn't hide the
mechanics from you and if you are trying to squeeze every clock cycle
out of your program, that is a good thing.

Hope that helps more than confuses.

joe
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top