简体   繁体   中英

C++ rely on implicit conversion to bool in conditions?

I found the following rule in a coding standards sheet :

Do not rely on implicit conversion to bool in conditions.

if (ptr) // wrong

if (ptr != NULL) // ok

How reasonable/usefull is this rule?

How much overload on the compiled code?

In the strictest sense, you can rely on implicit conversions to bool. Backwards compatibility with C demands it.

Thus it becomes a question of code readability. Often the purpose of code standards is to enforce a sameness to the code style, whether you agree with the style or not. If you're looking at someone else's standard and wondering if you should incorporate it into your own, go ahead and debate it - but if it's your company's long-standing rule, learn to live with it.

That rule puts you in a bind if you ever want to use a class that has an implicit conversion to bool , such as std::istream . This code reads a word at a time from a file until EOF is reached:

std::ifstream file("foo.txt");
std::string word;

while (file >> word)
{
    // do stuff
}

The stream extraction operator returns a reference to the file stream, which is implicitly converted to bool to indicate whether the stream is still in a good state. When you reach the end of the file, the test fails. Your coding standard precludes you from using this common construct.

For pointer types, it's not a big deal. The compiler will probably produce about the same code for the implicit conversion to bool and the explicit test against NULL . It's a matter of taste at that point - neither one is "better" in an absolute sense. The coding standard is simply trying to enforce a consistent style.

With that in mind, you should absolutely follow the coding standard when dealing with built-in types (pointers, ints, etc.). If you run into a similar situation to the above with a class having a legitimate conversion to bool , I would raise the issue with your teammates.

在大多数情况下,这是不可怕的,但如果你恰好键入你的意思也可以是更具可读性。

I wanted to add a historical view to this question.

ANSI C (aka C89/C90) was the first formal specification for C. Along withK&R C , you might notice something peculiar—there is no concept of a boolean. Control flow statements operate on expressions , and their flow is defined based on whether the expression evaluates to 0 or not. The lack of a boolean type is one of the biggest oversights of C. It wasn't until C99 that C gained the _Bool type, and defined macros for bool , true , and false in stdbool.h (note they are still integers). Likewise, C++ didn't originally have a boolean type, either, gaining it in C++98 with bool .

This is why there are implicit conversions to booleans. In my opinion, continuing to rely on that is bad design—booleans were added for a reason. true should always equal true , and the implicit conversion of all non-zero values as true is unsatisfactory.

NULL is also just a macro equal to zero, so specifically, for pointers in C++11, you should be using nullptr to determine if a pointer is null.

if(ptr != nullptr)
{
    // Do something with ptr.
}

This won't affect the compiled code at all.

As for how useful it is - it'll certainly aid comprehension for people coming from languages such as Java/C#. It'll make it more explicit what you're checking for. It'll throw a warning if you start comparing ints to NULL (and thereby indicate that you're hazy about the type of the variable in question). I personally prefer the first form, but it's not a totally unreasonable requirement.

Sometimes I think this rule can be broken, when eg dealing with standard libraries which return int instead of bool (for compatibility with C89).

However, this rule generally leads to easier-to-understand code. It's even enforced in languages like C# and it's not complained about too much there, so there are no major downsides to following this rule other than having to get used to it.

I dislike this rule very much. It is idiomatic in C++ to use the implicit conversion to bool for pointer types (and of course for boolean types). IMO, it is much easier to read

bool conditionMet = false;

while (!conditionMet) // read as "while condition is not met"
{
    /* do something */
}

than it is to read this:

bool conditionMet = false;

while (conditionMet == false) // read as "while conditionMet is false"
{
    /* do something */
}

It's the same for pointers. Also, by introducing the unnecessary comparison, you're introducing yet another opportunity to mistype and end up with an assignment instead of a comparison, which of course will produce undesired results. In cases where you're using ints as bools, as with old C code, I think you should also use the implicit conversion to bool.

增加零收益的规则是您可以有利地删除的规则。

That's an impressively stupid rule.

if (ptr != NULL) // ok

then why not

 if ((ptr != NULL)==true) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM