const reference vs. value

Discussion in 'C++' started by Michael Safyan, Aug 17, 2006.

  1. Dear members of comp.lang.c++,
    I am a little bit confused about the differences between constant
    references and values. I understand that it is faster to use a constant
    reference ("const T&") than a value ("T") since the former does not
    require copying whereas the latter does, is that correct? Also, I un
    derstand that "const T&" allows for polymorphism whereas "T" will
    generate code cuttting.
    On the former points, I am fairly confident... But I'm somewhat
    confused on how the two influence conversions. For example, suppose I
    define the following type:

    class Real{
    public:
    Real(int)
    Real(float);
    Real(double);
    Real(long double);
    ...
    Real operator+(Real);
    };

    Can I now write the following?
    Real x = 5.0;
    Real y = x + 3;
    //is above legal now if I don't define Real::eek:perator+(int)?

    Now, suppose I change the declaration+definition of
    Real::eek:perator+(Real) to Real::eek:perator+(const Real&), is the above
    still legal? Or do I need to modify the above to the following?

    Real x = 5.0;
    Real tmp = 3;
    Real y = x + tmp;

    **************************************

    In short, can one convert an unnamed constant to a constant reference or
    only to a value?
     
    Michael Safyan, Aug 17, 2006
    #1
    1. Advertising

  2. Michael Safyan posted:

    > Dear members of comp.lang.c++,
    > I am a little bit confused about the differences between constant
    > references and values. I understand that it is faster to use a constant
    > reference ("const T&") than a value ("T") since the former does not
    > require copying whereas the latter does, is that correct?



    Generalised answer: For large user-defined types, yes. For built-in types,
    no.

    In C++, references are "magical". The Standard says everything about how
    they behave, but absolutely nothing about what they actually are.

    In C, everything was passed by value, and everything was returned by value.
    If you wanted to alter an object in the calling function, then you passed
    its address. There was one other time, however, in C, where you passed the
    object's address: when the object type was large and it would have been
    more efficient to pass its address rather than passing the object by value.

    As mysterious as references may be, they're still apart of our world, and
    must obey the laws of our physics and so forth. If you have a scenario such
    as:

    struct PictureInfo {

    unsigned width;
    unsigned height;
    unsigned colour_depth;

    /* More members */
    };

    void Func(PictureInfo const &info)
    {
    /* Do stuff with the object */
    }

    Then the compiler will treat it as if you wrote:

    void Func(PictureInfo const *const p)

    For the most part, references are exactly like const pointers -- const
    pointers which you don't have to dereference.

    There's something special about "references to const" though. If you bind a
    "reference to const" to an R-value, then an object is created which lives
    until the reference goes out of scope. Writing the following:

    {
    int &r = 5;
    }

    is effectively like writing:

    {
    int const five = 5;
    int &r = five;
    }


    > Also, I un derstand that "const T&" allows for polymorphism whereas "T"
    > will generate code cuttting.



    Indeed. In general though, you should always be passing user-defined
    objects by reference to const, rather than by value.


    > On the former points, I am fairly confident... But I'm somewhat
    > confused on how the two influence conversions. For example, suppose I
    > define the following type:
    >
    > class Real{
    > public:
    > Real(int)
    > Real(float);
    > Real(double);
    > Real(long double);
    > ...
    > Real operator+(Real);
    > };
    >
    > Can I now write the following?
    > Real x = 5.0;
    > Real y = x + 3;
    > //is above legal now if I don't define Real::eek:perator+(int)?



    Question to Physics teacher:
    "I have an apple in my hand; if I let go of it, will gravity pull it to
    the ground?"

    Answer from Physics teacher:
    "Why are you asking *me* when you can try compile it with your own
    compiler?"


    > Now, suppose I change the declaration+definition of
    > Real::eek:perator+(Real) to Real::eek:perator+(const Real&), is the above
    > still legal? Or do I need to modify the above to the following?



    Would it be legal if you passed its address? References are just a fancy
    way of passing around addresses.

    --

    Frederick Gotham
     
    Frederick Gotham, Aug 17, 2006
    #2
    1. Advertising

  3. Frederick Gotham wrote:
    > Michael Safyan posted:
    >
    >> Dear members of comp.lang.c++,
    >> I am a little bit confused about the differences between constant
    >> references and values. I understand that it is faster to use a constant
    >> reference ("const T&") than a value ("T") since the former does not
    >> require copying whereas the latter does, is that correct?

    >
    >
    > Generalised answer: For large user-defined types, yes. For built-in types,
    > no.
    >
    > In C++, references are "magical". The Standard says everything about how
    > they behave, but absolutely nothing about what they actually are.
    >
    > In C, everything was passed by value, and everything was returned by value.
    > If you wanted to alter an object in the calling function, then you passed
    > its address. There was one other time, however, in C, where you passed the
    > object's address: when the object type was large and it would have been
    > more efficient to pass its address rather than passing the object by value.
    >
    > As mysterious as references may be, they're still apart of our world, and
    > must obey the laws of our physics and so forth. If you have a scenario such
    > as:
    >
    > struct PictureInfo {
    >
    > unsigned width;
    > unsigned height;
    > unsigned colour_depth;
    >
    > /* More members */
    > };
    >
    > void Func(PictureInfo const &info)
    > {
    > /* Do stuff with the object */
    > }
    >
    > Then the compiler will treat it as if you wrote:
    >
    > void Func(PictureInfo const *const p)
    >
    > For the most part, references are exactly like const pointers -- const
    > pointers which you don't have to dereference.
    >
    > There's something special about "references to const" though. If you bind a
    > "reference to const" to an R-value, then an object is created which lives
    > until the reference goes out of scope. Writing the following:
    >
    > {
    > int &r = 5;
    > }
    >
    > is effectively like writing:
    >
    > {
    > int const five = 5;
    > int &r = five;
    > }
    >
    >
    >> Also, I un derstand that "const T&" allows for polymorphism whereas "T"
    >> will generate code cuttting.

    >
    >
    > Indeed. In general though, you should always be passing user-defined
    > objects by reference to const, rather than by value.
    >
    >
    >> On the former points, I am fairly confident... But I'm somewhat
    >> confused on how the two influence conversions. For example, suppose I
    >> define the following type:
    >>
    >> class Real{
    >> public:
    >> Real(int)
    >> Real(float);
    >> Real(double);
    >> Real(long double);
    >> ...
    >> Real operator+(Real);
    >> };
    >>
    >> Can I now write the following?
    >> Real x = 5.0;
    >> Real y = x + 3;
    >> //is above legal now if I don't define Real::eek:perator+(int)?

    >
    >
    > Question to Physics teacher:
    > "I have an apple in my hand; if I let go of it, will gravity pull it to
    > the ground?"
    >
    > Answer from Physics teacher:
    > "Why are you asking *me* when you can try compile it with your own
    > compiler?"
    >

    Because not all compilers are conformant, and I have been having
    difficulty getting it to work either way. Although, I submit, I have
    been using a more complicated instance than the example given here.

    >
    >> Now, suppose I change the declaration+definition of
    >> Real::eek:perator+(Real) to Real::eek:perator+(const Real&), is the above
    >> still legal? Or do I need to modify the above to the following?

    >
    >
    > Would it be legal if you passed its address? References are just a fancy
    > way of passing around addresses.

    Yes, I understand that... Then I suppose I misstated the question.
    >


    The question is this:
    Given the two definitions type::func(const type&) and type::func(type),
    does the compiler use different rules to match these? Given
    type::type(int) and either type::func(const type&) or type::func(type),
    does the compiler accept type::func(5) in both cases? If not does it
    accept it in any case?
     
    Michael Safyan, Aug 17, 2006
    #3
  4. "Frederick Gotham" <> wrote in message
    news:nsREg.12762$...
    >
    > Question to Physics teacher:
    > "I have an apple in my hand; if I let go of it, will gravity pull it

    to
    > the ground?"
    >
    > Answer from Physics teacher:
    > "Why are you asking *me* when you can try compile it with your own
    > compiler?"


    Because my compiler might accept non-standard code?

    > Would it be legal if you passed its address? References are just a fancy
    > way of passing around addresses.


    References are just a way of renaming objects. That's all. They can be
    implemented by passing around addresses, but that's no requirement. For
    example:

    void fn(int &x) { x = 2*x; }

    This function would be horrible if implemented as pass-by-address, when x
    could simply be passed in and out by value. The compiler is free to
    implement the function this way, and it should.

    --
    Philip Potter
     
    Philip Potter, Aug 17, 2006
    #4
  5. Michael Safyan

    Greg Comeau Guest

    In article <nsREg.12762$>,
    Frederick Gotham <> wrote:
    >In C++, references are "magical". The Standard says everything about how
    >they behave, but absolutely nothing about what they actually are.


    This is true of many things though.

    >In C, everything was passed by value,


    And how are they passed now? :)

    Anyway, in C array's are not passed by value.

    >...
    > {
    > int &r = 5;
    > }
    >
    >is effectively like writing:
    >
    > {
    > int const five = 5;
    > int &r = five;
    > }


    No, that's an error. Actually both forms are. You probably mean
    const int &r
    --
    Greg Comeau / 20 years of Comeauity! Intel Mac Port now in alpha!
    Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
    World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
    Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
     
    Greg Comeau, Aug 17, 2006
    #5
  6. Michael Safyan

    Ron Natalie Guest

    Michael Safyan wrote:
    > Dear members of comp.lang.c++,
    > I am a little bit confused about the differences between constant
    > references and values. I understand that it is faster to use a constant
    > reference ("const T&") than a value ("T") since the former does not
    > require copying whereas the latter does, is that correct?


    Not necessarily. If the copying is trivial, you may introduce
    worse performance with the reference. For example, it's probably
    a lose with any numeric or pointer type. Small POD classes probably
    also may not be a win. However, when you've got something with a
    large amount of internally-managed dynamic memory, you are right.
    Using the original (read-only) rather than a copy is going to win.


    > Can I now write the following?
    > Real x = 5.0;
    > Real y = x + 3;
    > //is above legal now if I don't define Real::eek:perator+(int)?


    Yes, because you have converting constructors to go from int to Real.

    >
    > Now, suppose I change the declaration+definition of
    > Real::eek:perator+(Real) to Real::eek:perator+(const Real&), is the above
    > still legal? Or do I need to modify the above to the following?


    No problem, and this is specifically why you want to make it a
    CONST reference. A non-const reference could not be bound to
    the temporary converted value.

    > In short, can one convert an unnamed constant to a constant reference or
    > only to a value?


    If it will convert to a value, it will convert to a const-reference.
     
    Ron Natalie, Aug 17, 2006
    #6
  7. Michael Safyan

    Noah Roberts Guest

    OT: C parameter semantics was Re: const reference vs. value

    Greg Comeau wrote:
    > In article <nsREg.12762$>,
    > Frederick Gotham <> wrote:
    > >In C++, references are "magical". The Standard says everything about how
    > >they behave, but absolutely nothing about what they actually are.

    >
    > This is true of many things though.
    >
    > >In C, everything was passed by value,

    >
    > And how are they passed now? :)
    >
    > Anyway, in C array's are not passed by value.


    In C arrays are not passed at all. Arrays degrade to pointers any time
    they are used as an r-value. The pointer is passed by value to the
    function. Even when you use syntax such as:

    void c(int arr[]);

    arr is actually a pointer inside of 'c'. All the above syntax does is
    inform the human reader that the input is expected to be an array. To
    the compiler it means exactly the same thing as:

    void c(int * arr);
     
    Noah Roberts, Aug 17, 2006
    #7
  8. Ron Natalie wrote:
    > Michael Safyan wrote:
    >> Dear members of comp.lang.c++,
    >> I am a little bit confused about the differences between constant
    >> references and values. I understand that it is faster to use a
    >> constant reference ("const T&") than a value ("T") since the former
    >> does not require copying whereas the latter does, is that correct?

    >
    > Not necessarily. If the copying is trivial, you may introduce
    > worse performance with the reference. For example, it's probably
    > a lose with any numeric or pointer type. Small POD classes probably
    > also may not be a win. However, when you've got something with a
    > large amount of internally-managed dynamic memory, you are right.
    > Using the original (read-only) rather than a copy is going to win.
    >
    >
    >> Can I now write the following?
    >> Real x = 5.0;
    >> Real y = x + 3;
    >> //is above legal now if I don't define Real::eek:perator+(int)?

    >
    > Yes, because you have converting constructors to go from int to Real.
    >
    >>
    >> Now, suppose I change the declaration+definition of
    >> Real::eek:perator+(Real) to Real::eek:perator+(const Real&), is the above
    >> still legal? Or do I need to modify the above to the following?

    >
    > No problem, and this is specifically why you want to make it a
    > CONST reference. A non-const reference could not be bound to
    > the temporary converted value.
    >
    >> In short, can one convert an unnamed constant to a constant reference
    >> or only to a value?

    >
    > If it will convert to a value, it will convert to a const-reference.


    Thank you so much. That was exactly what I wanted to know.
     
    Michael Safyan, Aug 17, 2006
    #8
  9. Michael Safyan

    Greg Comeau Guest

    Re: OT: C parameter semantics was Re: const reference vs. value

    In article <>,
    Noah Roberts <> wrote:
    >Greg Comeau wrote:
    >> In article <nsREg.12762$>,
    >> Frederick Gotham <> wrote:
    >> >In C++, references are "magical". The Standard says everything about how
    >> >they behave, but absolutely nothing about what they actually are.

    >>
    >> This is true of many things though.
    >>
    >> >In C, everything was passed by value,

    >>
    >> And how are they passed now? :)
    >>
    >> Anyway, in C array's are not passed by value.

    >
    >In C arrays are not passed at all.


    In some cross-breeding of terms, actually more informally it's
    boinks into the realm of 'pass by reference' which is not
    about C++ references though some of the underlying machinery
    may be similar, and which has the semantics your desribe.
    --
    Greg Comeau / 20 years of Comeauity! Intel Mac Port now in alpha!
    Comeau C/C++ ONLINE ==> http://www.comeaucomputing.com/tryitout
    World Class Compilers: Breathtaking C++, Amazing C99, Fabulous C90.
    Comeau C/C++ with Dinkumware's Libraries... Have you tried it?
     
    Greg Comeau, Aug 18, 2006
    #9
    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. Replies:
    11
    Views:
    1,153
  2. Javier
    Replies:
    2
    Views:
    629
    James Kanze
    Sep 4, 2007
  3. George2
    Replies:
    10
    Views:
    641
    Pete Becker
    Dec 17, 2007
  4. 0m
    Replies:
    26
    Views:
    1,174
    Tim Rentsch
    Nov 10, 2008
  5. fungus
    Replies:
    13
    Views:
    954
    fungus
    Oct 31, 2008
Loading...

Share This Page