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) T开发者_StackOverflow社区he 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?
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.
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.
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.
精彩评论