Question

I have read Answers to C++ interview questions among which there is one that puzzles me:

Q: When are temporary variables created by C++ compiler?

A: Provided that function parameter is a "const reference", compiler generates temporary variable in following 2 ways.

a) The actual argument is the correct type, but it isn't Lvalue

double Cube(const double & num)
{
  num = num * num * num;
  return num;
}

double temp = 2.0;
double value = cube(3.0 + temp); // argument is a expression and not a Lvalue

b) The actual argument is of the wrong type, but of a type that can be converted to the correct type

 long temp = 3L;
 double value = cuberoot(temp); // long to double conversion

My question is once the function argument is a const reference, why does the compiler generate the temporary variable, isn't that self-contradictory? Also, should the function Cube fail to compile because it modifies the const argument?

Was it helpful?

Solution

You are allowed to pass the results of an expression (including that of implicit casting) to a reference-to-const. The rationale is that while (const X & value) may be cheaper to use, depending on the copy-cost of type type X, than (X value), the effect is pretty much the same; value gets used but not modified (barring some dicey const-casting). Hence it is harmless to allow a temporary object to be created and passed to the function.

You are not allowed to do so with pointer-to-const or reference-to-non-const, because unexpected (and bad) things can happen, such as you might expect the long temp to be cast back to long, which isn't going to happen.

You're correct about num = num * num * num; being invalid. That's a bug in the text, but the argument made by it holds.

OTHER TIPS

I don't see anything self-contradictory here. If the argument is not an lvalue, or is of wrong type, the reference cannot be attached directly to the argument for obvious reasons; hence the need for an intermediate temporary of the correct type. The reference is attached to that temporary instead.

The Cube function is indeed broken (ill-formed) since it attempts to modify a const value.

Looks wrong to me - and gcc generates an error:

const_ref.cpp: In function ‘double cube(const double&)’:
const_ref.cpp:3: error: assignment of read-only reference ‘num’

The compiler can generate a temporary variable. It doesn't have to.

And yes, Cube should not actually compile.

Because in both examples, there is no non-temporary object of the correct type.

I believe that you are correct about the function cube failing to compile. Anyway, that should fail, and it does on my compiler (VC++ 2008).

As for creating a temporary:

A temporary value to back the const reference will be created whenever the actual argument:

i) is not of the correct type for the reference and, ii) can be implicitly converted to the correct type.

In example a) from your question, a temporary double is created to hold the value 3.0 + temp. Then Cube() is called with a const reference to the temporary. This is because you can't have a reference to 3.0 + temp because that isn't a variable (it is an rvalue -- the result of an expression) and so it has no memory address, and can't back the reference. Implicitly, the compiler will create a temporary double and then assign it the value of 3.0 + temp.

In your example b), you have a long, but your function requires a double. The compiler will implicitly convert a long to a double. It does this by creating a temporary double, assigning it the converted value of temp, and then creating a const reference to the temporary, and passing that reference to cuberoot

Yes. Cube(), as you've shown it here, should fail to compile.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top