C++ question

Started by
5 comments, last by HughG 19 years, 3 months ago
I'm reading a book by Bjarne Stroustrup and cannot figure out what he is trying to say by the below statement: //---------------------<Book exerpt>------------------------\ A literal, a constant, and an argument that requires conversion can be passed as a const& argument, but not as a nonconst argument. Allowing conversions for a const T& argument ensures that such an argument can be given exactly the same set of values as a T argument by passing the value in a temporary, if necessary. For example: float fsqrt(const float&) ; / / Fortranstyle sqrt taking a reference argument void g(double d) { float r = fsqrt(2.0f) ; / / pass ref to temp holding 2.0f r = fsqrt(r) ; / / pass ref to r r = fsqrt(d) ; / / pass ref to temp holding float(d) } Disallowing conversions for nonconst reference arguments (§5.5) avoids the possibility of silly mistakes arising from the introduction of temporaries. For example: Section 7.2 Argument Passing 147 void update(float& i) ; void g(double d, float r) { update(2.0f) ; / / error: const argument update(r) ; / / pass ref to r update(d) ; / / error: type conversion required } Had these calls been allowed, update() would quietly have updated temporaries that immediately were deleted. Usually, that would come as an unpleasant surprise to the programmer. //--------------------------<End exerpt>--------------------\ TIA
Advertisement
float func1(float f);float func2(const float f);float func3(const float & f);
Of these three functions, only func3 will accept a literal value (3.142f), a constant (const float EPSILON = 0.001f) and an argument that requires conversion (12) in addition to a type-appropriate argument.
Quote:Original post by Oluseyi
float func1(float f);float func2(const float f);float func3(const float & f);
Of these three functions, only func3 will accept a literal value (3.142f), a constant (const float EPSILON = 0.001f) and an argument that requires conversion (12) in addition to a type-appropriate argument.


Ok, understood. My next question is why the 2 update functions don't work. I can sort of see why passing a literal by reference doesn't make sense but I don't see what problems it could cause. And I'm really confused as to why you would have to declare the parameter const just to type cast it. He mentions something about temporaries (I'm guessing local variables) but I'm still scratching my head.
Quote:Original post by HughG
Ok, understood. My next question is why the 2 update functions don't work. I can sort of see why passing a literal by reference doesn't make sense but I don't see what problems it could cause.
Syntactically making modifying a literal - a nonsensical operation - valid. Correctness is an important, albeit abstract, concept, and one the programming language should do as much as possible to enforce. Because C++ performs static type checking and resolution, it can't merely discard things that "don't make sense."

Quote:And I'm really confused as to why you would have to declare the parameter const just to type cast it. He mentions something about temporaries (I'm guessing local variables) but I'm still scratching my head.
All values must exist somewhere. Unless explicitly assigned to storage, that somewhere is a temporary variable created by the compiler, with an address and so forth. This holds for automatic type conversions as well. Modifying those temporaries would be invalid, so the reference must be constant.
Thanks for your explanation and patience Oluseyi!

I still don't understand...

void update(float& i) ;
void g(double d, float r)
{
update(2.0f) ; / / error: const argument
update(r) ; / / pass ref to r
update(d) ; / / error: type conversion required
}

Ok, so if update(d) was allowed, what problems could arise? I understand that d is type casted to a float automatically, and this conversion is done temporarily. Why does it matter if the cast is temporary or permanent? Say update just adds one to the number.. Why does it matter if it casts the double to a float and adds one to it? And how does making it constant solve the problem?
void update(float& i) ;
void g(double d, float r)
{
update(2.0f) ; / / error: const argument
update(r) ; / / pass ref to r
update(d) ; / / error: type conversion required
}

Since the value you are passing isn't constant, it assumes that you can edit the value. If you pass a number, you can't edit the number so that isn't allowed. passing r is fine because it is a float. passing d isn't ok because it isn't a float and requires a cast. But you can't cast something and then give a reference to it (and allow yourself to be able to alter the initial value passed).

if update adds 1 to whatever is passed, then 2.0f would become a literal reference with a value of 3.0 (everywhere you use 2.0f actually ends up with a value of 3.0). That doesn't make much sense.
And for d, it would require recasting the result back as a double and C++ isn't designed to cast a modifiable reference back and forth.

If you pass it by const, it means you can't modify that value, so 2.0f can't be altered to anything else, neither can d or r, so even if a cast is taken place, the original value of d will not change.

Sorry if you are still confused.
Great! Beautifully put. So the const is there just to make sure the rules dont get violated. I see why it won't work with 2.0f and think I understand why it won't work by passing the function a double. I guess I was confused on the implicit type casting and assumed that the function would perform properly if forced to cast. So the only reason to even pass it a double then is if the function you are passing needed it for whatever reason (read only). And to actually modify the initial double you would have to write a new function that accepts doubles instead of floats...

I think I got it. Thanks!

This topic is closed to new replies.

Advertisement