must pass by value

Discussion in 'C++' started by pauldepstein@att.net, Sep 16, 2006.

  1. Guest

    My texts give plenty of examples where passing by reference is
    necessary. For instance, the famous swap example.

    However, I've never seen an example where passing a variable by value
    is necessary.

    One place where I've seen passing by value recommended is in the
    throwing of exceptions. However, my texts never say why throwing by
    reference is wrong. (Of course, lots of people have explained why
    catching by value is poor practice.) Suppose I did throw by reference
    using namespace std; and including the correct exceptions libraries.
    Could I then write:

    throw &runtime_error("Incorrect...blah blah ");

    Or would this code be incorrect? My thinking is that a runtime_error
    is initialized with the string "Incorrect...blah blah " and that a
    reference to that error is thrown.

    Can anyone give a link to or give an example where the technique of
    passing by value is necessary to make a function work, and where
    passing by reference would lead to problems.

    I see two reasons to sometimes pass by value (not sure if this is
    correct). 1) Passing by value is quicker for simple built-in types
    like int. 2) Passing by value is easier to code (though the greater
    ease probably only makes a difference to beginners.)

    This doesn't seem enough of a reason for the language to include the
    passing-by-value concept.

    Are there reasons not to pass everything by value?


    Thank you for your explanations.

    Paul Epstein
     
    , Sep 16, 2006
    #1
    1. Advertising

  2. Guest

    I suppose one disadvantage would be that you could not concurrently
    modify the input when it is a reference... this is no problem most
    times, but I suppose there are situations where you might not want to
    have to lock the passed value until the caller finishes with it.

    just a thought


    wrote:
    > My texts give plenty of examples where passing by reference is
    > necessary. For instance, the famous swap example.
    >
    > However, I've never seen an example where passing a variable by value
    > is necessary.
    >
    > One place where I've seen passing by value recommended is in the
    > throwing of exceptions. However, my texts never say why throwing by
    > reference is wrong. (Of course, lots of people have explained why
    > catching by value is poor practice.) Suppose I did throw by reference
    > using namespace std; and including the correct exceptions libraries.
    > Could I then write:
    >
    > throw &runtime_error("Incorrect...blah blah ");
    >
    > Or would this code be incorrect? My thinking is that a runtime_error
    > is initialized with the string "Incorrect...blah blah " and that a
    > reference to that error is thrown.
    >
    > Can anyone give a link to or give an example where the technique of
    > passing by value is necessary to make a function work, and where
    > passing by reference would lead to problems.
    >
    > I see two reasons to sometimes pass by value (not sure if this is
    > correct). 1) Passing by value is quicker for simple built-in types
    > like int. 2) Passing by value is easier to code (though the greater
    > ease probably only makes a difference to beginners.)
    >
    > This doesn't seem enough of a reason for the language to include the
    > passing-by-value concept.
    >
    > Are there reasons not to pass everything by value?
    >
    >
    > Thank you for your explanations.
    >
    > Paul Epstein
     
    , Sep 16, 2006
    #2
    1. Advertising

  3. Bo Persson Guest

    wrote:
    > My texts give plenty of examples where passing by reference is
    > necessary. For instance, the famous swap example.
    >
    > However, I've never seen an example where passing a variable by
    > value
    > is necessary.


    That comes from the C language, where pass by value was the norm, and
    references isn't available.

    >
    > One place where I've seen passing by value recommended is in the
    > throwing of exceptions. However, my texts never say why throwing by
    > reference is wrong. (Of course, lots of people have explained why
    > catching by value is poor practice.) Suppose I did throw by
    > reference
    > using namespace std; and including the correct exceptions libraries.
    > Could I then write:
    >
    > throw &runtime_error("Incorrect...blah blah ");
    >
    > Or would this code be incorrect? My thinking is that a
    > runtime_error
    > is initialized with the string "Incorrect...blah blah " and that a
    > reference to that error is thrown.


    Don't know really. What would be the advantage? The throwing logic
    will often have to make a copy anyway, to ensure that the exception is
    available at a far away catch point.

    >
    > Can anyone give a link to or give an example where the technique of
    > passing by value is necessary to make a function work, and where
    > passing by reference would lead to problems.


    One advantage of call by value is that the function gets its own copy
    of the parameter. That ensures that nobody else is fiddling with it at
    the same time. It can also be used as a local work space inside the
    function.

    >
    > I see two reasons to sometimes pass by value (not sure if this is
    > correct). 1) Passing by value is quicker for simple built-in types
    > like int.


    Not by much. Having your own copy may make the functions machine code
    simpler though.

    > 2) Passing by value is easier to code (though the greater
    > ease probably only makes a difference to beginners.)


    Passing by value and passing by const reference looks pretty much the
    same, both att the call site and inside the fucntion.

    >
    > This doesn't seem enough of a reason for the language to include the
    > passing-by-value concept.


    For C++ it is inherited from C, where it was the only one.

    >
    > Are there reasons not to pass everything by value?
    >


    Sometimes you want to update the parameter, which can be done with a
    non-const reference.


    Bo Persson
     
    Bo Persson, Sep 16, 2006
    #3
  4. Guest

    wrote:
    > I suppose one disadvantage would be that you could not concurrently
    > modify the input when it is a reference... this is no problem most
    > times, but I suppose there are situations where you might not want to
    > have to lock the passed value until the caller finishes with it.
    >
    > just a thought
    >


    Either I misunderstand you or you are wrong. (I'm happy to assume my
    poor understanding is at fault.)

    I coded and ran the following program successfully:

    #include <iostream>
    using namespace std;

    int main()
    {
    int y = 1;
    int f(int&);
    cout << f(y);
    cin.get();

    }

    int f(int &x)
    { x = x +2;
    return x;}

    I therefore appear to have modified the input. (Though I don't know
    whether I "concurrently" modified it.)

    x = x+2 modifies input with the reference call f(int &x) so it appears
    (to me) that I have contradicted your posting.

    Thanks,

    Paul
     
    , Sep 16, 2006
    #4
  5. Jens Theisen Guest

    writes:

    > However, I've never seen an example where passing a variable by value
    > is necessary.


    To some extend, it's a convenience for a copy, and you're not
    disputing the necessity for making copies, are you?

    Also, there is a major argument dealing with lifetime.

    References generally don't extend lifetime of the object they refer
    to. If the language provided no value semantics, how would you
    transfer ownership to a function? The calling code would need to
    ensure that the reference is valid until it's not needed anymore.

    In fact, this is pretty much what C has: You can pass by value only in
    a "built-in" sense, ie. you can pass objects only by bit-wise
    copies. So, if you want to transfer ownership, the language will not
    help you.

    C++ on the other hand, has smart pointer which are, when passed by
    value, transfer ownership (or other things, depending on the smart
    pointer).

    > throw &runtime_error("Incorrect...blah blah ");


    This is not throwing by reference but by pointer, and does so in a
    wrong way. The catch handler will get a pointer to the memory where
    the temporary runtime_error has once been. Using that pointer is
    undefined behaviour.

    Better is

    throw new runtime_error("...");

    However, you now have to delete the exception in all your catch
    handlers that could catch it. That's error prone and thus

    throw runtime_error("...");

    is preferred.

    > Are there reasons not to pass everything by value?


    I think you mean by reference. As a particular compelling example, try
    do define the following function sensibly and run your solution:

    int const& product(int const& lhs, int const& rhs)
    {
    ...
    }

    Regards,

    Jens
     
    Jens Theisen, Sep 16, 2006
    #5
  6. <> wrote in message
    news:...

    > This doesn't seem enough of a reason for the language to include the
    > passing-by-value concept.


    Well, strictly speaking, it's not necessary -- you can accomplish the same
    thing by passing a reference and copying it yourself.

    However, there are times when it is useful. For example:

    void reduce(vector<double>& v, const double& x)
    {
    for (vector<double>::iterator it = v.begin(); it != v.end(); ++it)
    *it /= x;
    }

    This function divides every element of a vector by a given value. Now
    suppose we call it this way:

    vector<double> v;
    v.push_back(10);
    v.push_back(20);
    reduce(v, v[0]);

    You might think that the call

    reduce(v, v[0]);

    would have the same effect as

    reduce(v, 10);

    because the value of v[0] is 10. You would be wrong.

    What happens is that v[0] gets set to v[0]/v[0], which is, 1, and then v[1]
    gets set to v[1]/v[0]. Because v[0] is now 1, the effect is to leave the
    value of v[1] unchanged.

    If "const double& x" is changed to "double x", the problem goes away.
     
    Andrew Koenig, Sep 19, 2006
    #6
  7. Old Wolf Guest

    Jens Theisen wrote:
    > writes:
    >
    > > throw &runtime_error("Incorrect...blah blah ");

    >
    > This is not throwing by reference but by pointer, and does so in a
    > wrong way. The catch handler will get a pointer to the memory where
    > the temporary runtime_error has once been. Using that pointer is
    > undefined behaviour.


    Actually this code is ill-formed; you can't take the address of a
    temporary.
     
    Old Wolf, Sep 19, 2006
    #7
  8. Jens Theisen Guest

    "Old Wolf" <> writes:

    > Actually this code is ill-formed; you can't take the address of a
    > temporary.


    I don't think that is true. Temporaries are objects as any other, and
    putting an ampersand before them has the same semantics as for any
    other object.

    Jens
     
    Jens Theisen, Sep 19, 2006
    #8
  9. Jens Theisen posted:

    >> Actually this code is ill-formed; you can't take the address of a
    >> temporary.

    >
    > I don't think that is true. Temporaries are objects as any other, and
    > putting an ampersand before them has the same semantics as for any
    > other object.



    A "nameless object", as they're called, is an R-value, not an L-value. One
    cannot take the address of an R-value; the compiler must issue a diagnostic
    if you attempt to do so.

    The following won't compile:

    int main()
    {
    int() = 5; /* Can't assign to an R-value */
    int *p = &int(); /* Can't take address of R-value */
    }

    The reason why it works with user-defined types is that the two lines are
    interpreted respectively as:

    MyClass().operator=(5);
    MyClass *p = MyClass().operator&();

    Whether you think this is appropriate or not is a topic for comp.std.c++.

    --

    Frederick Gotham
     
    Frederick Gotham, Sep 19, 2006
    #9
  10. Kai-Uwe Bux Guest

    Jens Theisen wrote:

    > "Old Wolf" <> writes:
    >
    >> Actually this code is ill-formed; you can't take the address of a
    >> temporary.

    >
    > I don't think that is true. Temporaries are objects as any other, and
    > putting an ampersand before them has the same semantics as for any
    > other object.


    From the standard [5.3.1/2]

    The result of the unary & operator is a pointer to its operand. The
    operand shall be an lvalue or a qualified-id.


    Note that in

    &runtime_error("Incorrect...blah blah ")

    the operator & is applied to neither an lvalue nor a qualified-id.


    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Sep 19, 2006
    #10
  11. Kai-Uwe Bux Guest

    Frederick Gotham wrote:

    [snip]
    > The following won't compile:
    >
    > int main()
    > {
    > int() = 5; /* Can't assign to an R-value */
    > int *p = &int(); /* Can't take address of R-value */
    > }
    >
    > The reason why it works with user-defined types is that the two lines are
    > interpreted respectively as:
    >
    > MyClass().operator=(5);
    > MyClass *p = MyClass().operator&();


    Ah, I missed that.


    Thanks

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Sep 19, 2006
    #11
  12. * Kai-Uwe Bux:
    > Frederick Gotham wrote:
    >
    > [snip]
    >> The following won't compile:
    >>
    >> int main()
    >> {
    >> int() = 5; /* Can't assign to an R-value */
    >> int *p = &int(); /* Can't take address of R-value */
    >> }
    >>
    >> The reason why it works with user-defined types is that the two lines are
    >> interpreted respectively as:
    >>
    >> MyClass().operator=(5);
    >> MyClass *p = MyClass().operator&();

    >
    > Ah, I missed that.
    >


    I don't see the original posting, but I don't think you missed anyhing:
    the compiler does not generate an operator& automatically for a
    user-defined data type. It's the plain old built-in one that comes into
    play unless the class defines an operator&, and the built-in one can't
    be applied to a temporary -- although a compiler may allow that as a
    language extension, similar to passing a T temporary to a T& argument
    (also, as I recall there was an error in early editions of "Thinking in
    C++" where operator& was listed among the auto-generated ones).

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Sep 20, 2006
    #12
  13. Kai-Uwe Bux Guest

    Alf P. Steinbach wrote:

    > * Kai-Uwe Bux:
    >> Frederick Gotham wrote:
    >>
    >> [snip]
    >>> The following won't compile:
    >>>
    >>> int main()
    >>> {
    >>> int() = 5; /* Can't assign to an R-value */
    >>> int *p = &int(); /* Can't take address of R-value */
    >>> }
    >>>
    >>> The reason why it works with user-defined types is that the two lines
    >>> are interpreted respectively as:
    >>>
    >>> MyClass().operator=(5);
    >>> MyClass *p = MyClass().operator&();

    >>
    >> Ah, I missed that.
    >>

    >
    > I don't see the original posting,


    My posting is a sibling to Frederick Gotham's posting, which I quoted.

    > but I don't think you missed anyhing:
    > the compiler does not generate an operator& automatically for a
    > user-defined data type. It's the plain old built-in one that comes into
    > play unless the class defines an operator&, and the built-in one can't
    > be applied to a temporary -- although a compiler may allow that as a
    > language extension, similar to passing a T temporary to a T& argument
    > (also, as I recall there was an error in early editions of "Thinking in
    > C++" where operator& was listed among the auto-generated ones).


    Clearly, I am getting sleepy: g++ confused me by not producing an error but
    just a warning. Comeau does give an error on:

    #include <stdexcept>

    int main ( void ) {
    & std::runtime_error( "hello" );
    }

    That is in line with my original expectations.


    Thanks

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Sep 20, 2006
    #13
  14. Jens Theisen Guest

    Kai-Uwe Bux <> writes:

    > From the standard [5.3.1/2]
    >
    > The result of the unary & operator is a pointer to its operand. The
    > operand shall be an lvalue or a qualified-id.


    Sorry, I should have checked.

    Jens
     
    Jens Theisen, Sep 20, 2006
    #14
    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. Jerry
    Replies:
    20
    Views:
    8,041
    Roedy Green
    Sep 9, 2005
  2. NeoGeoSNK
    Replies:
    25
    Views:
    973
    NeoGeoSNK
    Nov 24, 2006
  3. venkatagmail
    Replies:
    11
    Views:
    715
    James Kanze
    Oct 3, 2007
  4. Vols
    Replies:
    3
    Views:
    396
    Ian Collins
    Apr 28, 2008
  5. Tricky
    Replies:
    0
    Views:
    609
    Tricky
    Mar 19, 2009
Loading...

Share This Page