Which is better: NULL or false?
I've been programming with SDL for a while, and I decide to make a header file to simp开发者_开发知识库lify my coding. Now I have a question; if I pass a function parameter I don't want, should I do
test(NULL);
from the Windows API I include or
test(false);
I use C++, NOT C.
It completely depends on what the function parameter type is. If it's a pointer, and the documentation says that it's valid, then you can pass the C++ NULL
(which is just 0
in reality).
Examples:
// Bad; strlen expects a pointer to a real, existing C-string buffer
std::cout << strlen(NULL);
/**
* Function that does something.
*
* @param ptr Pointer to buffer, or NULL to do nothing
*/
void myFunc(const char* ptr);
// OK; the function is designed to be ok with it
myFunc(NULL);
So not all functions will accept this as valid for a pointer.
It certainly won't be valid for any other type (though you'll get away with passing it for an int
, it's not quite what you'd expect to do). NULL
is not a catch-all "I want to opt out of this function parameter". You simply can't do that in the general case.
Conclusion: It depends what test
is.
And I have no idea what null
is supposed to be.
Tomalak's answer is great advice for calling existing functions. When you're writing a function (or when you are free to change the function) and you want parameters to be optional, you should try to design it so the usage is correct, intuitive and self-documenting. If we compare:
1) bool really_test = ...;
test(really_test, my_test);
2) if (...)
test(my_test);
3) test(... ? &my_test : NULL);
2) is more comprehensible for using if
- a universally understood keyword, and not simply implying that the function's first argument can be set to bypass the test. The dangerous scenario is that someone writes code like 3) misremembering or misunderstanding the API; it works happily until that NULL condition is satisfied (which might be in prod rather than testing).
Similarly, when some behaviour is optional, I prefer to use an enum to document those options instead of a boolean that communicates nothing at the call site. Contrast...
test(false);
test(true);
...with...
test(Text_Output);
test(Html_Output);
If there are multiple arguments, then it can be useful to use a sentinel such as NULL to indicate that some of them aren't applicable. It's harder to get this wrong if the arguments are of distinct type:
test(my_test, /* output stream */ NULL, &error_counter, /* skip list */ NULL);
In such usage, you can expect a compile-time error if an argument is accidentally omitted or the order is wrong.
When the compiler can't check the argument order/count it's dangerous:
test(&my_test /* mandatory, this one has three stages */,
/* stderr else out */ true, /* update counters */ false,
/* skip 1st stage */ true, /* skip 2nd */ false, /* skip 3rd */ true);
That might satisfy...
test(Test*, bool use_error_stream, bool update_counters, ...);
...which would be a spectacularly bad API.
Note that references mandatorily point to a valid object, so some people like to use them where possible to communicate the fact the option is mandatory. Other people think it's more important to hint at whether a parameter is modifiable at the call site, and write functions accepting non-const pointers:
f(my_object); // obviously mandatory, but is it const or not?
f(&my_object); // _might_ be modifiable (if that conventions followed),
// but is it mandatory or not?
null
is a Java (and C#) keyword. It has no business showing up in C++ code.
nullptr is the way to go. VC++10 already supports it. GCC will support it in 4.6
精彩评论