References or pointers?

Discussion in 'C++' started by desktop, Sep 5, 2007.

  1. desktop

    desktop Guest

    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?
    desktop, Sep 5, 2007
    #1
    1. Advertising

  2. "desktop" <> ha scritto nel messaggio
    news:fbljr2$48m$-c.dk...
    >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
    Carlo Capelli, Sep 5, 2007
    #2
    1. Advertising

  3. desktop

    terminator Guest

    On Sep 5, 9:54 am, desktop <> wrote:
    > 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.
    terminator, Sep 5, 2007
    #3
  4. "Carlo Capelli" <> wrote in message
    news:ZbtDi.6287$...
    [...]
    > You can think to references as 'syntax sugar' for const pointers


    Indeed.
    Chris Thomasson, Sep 5, 2007
    #4
  5. desktop

    desktop Guest

    terminator wrote:
    > On Sep 5, 9:54 am, desktop <> wrote:
    >> 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:


    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.
    desktop, Sep 5, 2007
    #5
  6. desktop

    desktop Guest

    Carlo Capelli wrote:
    > "desktop" <> ha scritto nel messaggio
    > news:fbljr2$48m$-c.dk...
    >> 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.



    Ok thats a very good explanation, thanks!


    >> 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.


    I know but the example is also made to show what happens if you DON'T
    pass an object as pointer or reference.
    desktop, Sep 5, 2007
    #6
  7. desktop

    terminator Guest

    On Sep 5, 2:41 pm, desktop <> wrote:
    > terminator wrote:
    > > On Sep 5, 9:54 am, desktop <> wrote:
    > >> 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:

    >
    > 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.
    terminator, Sep 5, 2007
    #7
  8. desktop

    SasQ Guest

    On Wed, 05 Sep 2007 02:46:08 -0700, Chris Thomasson wrote:

    >> You can think to references as 'syntax sugar' for
    >> const pointers

    >
    > Indeed.


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

    --
    SasQ
    SasQ, Sep 5, 2007
    #8
  9. desktop

    Old Wolf Guest

    On Sep 5, 9:46 pm, "Chris Thomasson" <> wrote:
    > "Carlo Capelli" <> wrote in message
    >
    > > You can think to references as 'syntax sugar' for const pointers

    >
    > Indeed.


    If you like fostering misconceptions about the language, that is.
    Old Wolf, Sep 6, 2007
    #9
  10. "Old Wolf" <> wrote in message
    news:...
    > On Sep 5, 9:46 pm, "Chris Thomasson" <> wrote:
    >> "Carlo Capelli" <> wrote in message
    >>
    >> > You can think to references as 'syntax sugar' for const pointers

    >>
    >> Indeed.

    >
    > If you like fostering misconceptions about the language, that is.


    Okay: I am wrong.
    Chris Thomasson, Sep 6, 2007
    #10
  11. "SasQ" <> wrote in message
    news:p...
    > On Wed, 05 Sep 2007 02:46:08 -0700, Chris Thomasson wrote:
    >
    >>> You can think to references as 'syntax sugar' for
    >>> const pointers

    >>
    >> Indeed.

    >
    > 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.
    Chris Thomasson, Sep 6, 2007
    #11
  12. desktop

    Joe Greer Guest

    "Chris Thomasson" <> wrote in
    news::

    > "SasQ" <> wrote in message
    > news:p...
    >> On Wed, 05 Sep 2007 02:46:08 -0700, Chris Thomasson wrote:
    >>
    >>>> You can think to references as 'syntax sugar' for
    >>>> const pointers
    >>>
    >>> Indeed.

    >>
    >> 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.
    >
    >


    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
    Joe Greer, Sep 6, 2007
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Roger Leigh
    Replies:
    8
    Views:
    415
    Karl Heinz Buchegger
    Nov 17, 2003
  2. Replies:
    3
    Views:
    434
    Victor Bazarov
    Nov 10, 2004
  3. DanielEKFA
    Replies:
    8
    Views:
    587
    DanielEKFA
    May 16, 2005
  4. Replies:
    8
    Views:
    694
    Bruno Desthuilliers
    Dec 12, 2006
  5. cerr

    pointers, pointers, pointers...

    cerr, Apr 7, 2011, in forum: C Programming
    Replies:
    12
    Views:
    653
Loading...

Share This Page