问题
Bjarne suggests using the condition in if's as scope restriction. In particular this example.
if ( double d = fd() ) {
// d in scope here...
}
I'm curios how to interpret the declaration in a true / false sense.
- It's a declaration
- It's a double.
Edit: It's in 6.3.2.1 The C++ programming language as a recommendation.
Edit2: templatetypedefs suggestion of pointers, in particular with dynamic casts, might give insight to Bjarnes suggestion.
SteveJessop tells me: - A condition is not an expression it can also be a declaration, the value used, is the value being evaluated.
回答1:
The code that you're seeing is a specialized technique for declaring variables in if
statements. You commonly see something like this:
if (T* ptr = function()) {
/* ptr is non-NULL, do something with it here */
} else {
/* ptr is NULL, and moreover is out of scope and can't be used here. */
}
A particularly common case is the use of dynamic_cast
here:
if (Derived* dPtr = dynamic_cast<Derived*>(basePtr)) {
/* basePtr really points at a Derived, so use dPtr as a pointer to it. */
} else {
/* basePtr doesn't point at a Derived, but we can't use dPtr here anyway. */
}
What's happening in your case is that you're declaring a double
inside the if
statement. C++ automatically interprets any nonzero value as true
and any zero value as false
. What this code means is "declare d
and set it equal to fd()
. If it is nonzero, then execute the if
statement."
That said, this is a Very Bad Idea because double
s are subject to all sorts of rounding errors that prevent them from being 0 in most cases. This code will almost certainly execute the body of the if
statement unless function
is very well-behaved.
Hope this helps!
回答2:
In the example Stroustrup gives, the code in the if
block divides a value by d
:
if (double d = prim(true)) {
left /= d;
break;
}
Division by 0 is undefined behavior, so it makes some sense in this case to test d
against the value 0.0
before dividing. Putting the definition in the condition is a convenient way to do this, for the reasons Stroustrup states.
Your code gives no reason why the value 0.0
would be special, and therefore it is not clear why anyone would combine the definition of d
with that test. Only use Stroustrup's pattern when "false" values of the type you're defining need to be treated specially. Otherwise just do this:
{
double d = fd();
// d in scope here...
}
回答3:
It is both a declaration and a double. This is quite equivalent to
{
double d = fd();
if (d) {
}
}
However, this pattern is worth the small additional syntax to simplify, as it is fairly useful and common. In addition, the transformation is less obvious once you start adding else clauses, as d
is out of scope for them.
Also, as others have noted, it's useful in general but FP types in specific have some issues when compared against 0.
回答4:
the if
statement predicates on the value that is assigned to the variable in the assignment expression. If the double evaluates to anything but 0.0 it will run the code inside.
Note that you are not supposed to compare doubles with zero, but it generally works in my experience.
Basically, you shouldn't do this.
The other contributors to this topic have found that this expression is used to exclude the zero case so as to avoid a divide-by-zero. That's definitely smart and such a situation legitimizes this usage as far as I'm concerned (but do consider the confusion such code may cause).
来源:https://stackoverflow.com/questions/11217179/double-as-true-false