Neil said:
Not confusing: in C and C++ it is illegal to modify string literals, thus,
even if the programmer were sloppy enough not to check the function signature,
the programmer would still know that " blah blah " would not get modified.
That doesn't really matter... This literal could be hidden through some
preprocessor variable, a const buried in some headers or a return value
from some other function. It's just one out of a million comparable cases.
Fortunately the compiler will detect the error, no matter why the
programmer wrote such code (maybe he/she is a beginner and doesn't know
better?)
Furthermore, your example is not a good one because the following code is
legal according to the C++ standard,
no, it's not. see below.
but according to your point of view
still more confusing than the illegal code you posted: here we have
a pointer to dynamically allocated memory. If the programmer doesn't
check the function signature, then, according to your point of view,
the programmer might think trim_whitespace() may call realloc on
blah (which it doesn't, since it takes an str, hence must call
construct a separate string first).
That's what I'm trying to explain. And there are many more cases where
the error is not so obvious. Again: Because implicit conversions are
performed, even you might involuntaryly write such code. If you really
want the "wrong" (or "unobvious") behavior, you can still explicitly say so.
void trim_whitespace(string& str);
int main()
{
char *blah = malloc(12);
strcpy(blah, " blah blah ");
trim_whitespace(blah);
return 0;
}
This code is illegal and should not compile for two reasons:
1) malloc returns void* which cannot be converted to char* (but I guess
it's just a typo)
2) in the call to trim_whitespace, a temporary std::string has to be
constructed and bound to a reference to non-const string. Constructing a
string is allowed, but binding the temporary string to a reference to
non-const is not (see 13.3.3.1.4/3).
Actually the standard also says that references to non-const cannot be
bound to r-values [13.3.2/3], but IMHO that's more or less the same in
our context (although I'm not a language lawyer
)
So according to your point of view, why is the modified
I posted allowed by C++? All you said applies to the
modified code snippet I posted as well.
As I said, it's _not_ allowed and you've provided a nice example that
shows why it isn't allowed
Not true. Think about OpenGL where you must necessarily use globals to
save and restore state. Also, think about programs where you pass in an
object and the function returns another one (instead of being a void one
like the one in the example I gave). Think of all those functions that
take CONST references. There is no usually: it depends.
You've lost me here... What do you mean by this? That const-correctness
is not as widely spread as it should be?
Because we often don't need to modify what we pass in or use it again at all:
void foo(const int i) {
if (i == 0)
std::cout << "hello" << std::endl;
else
std::cout << "good night" << std::endl;
}
int main() {
foo(0);
foo(1);
}
I was talking about the case where foo takes an int&
void calc(int& result) {
result = /* some calculation */;
// the only visible effects of calc() are
// the effects caused to the result parameter
// calc does not modify any global variables,
// do I/O, etc. or call other functions that might do
}
int main()
{
// let calc() do something, but I don't care for the result
// If the compiler is smart enough, it will optimize the
// entire function call away - What has been gained by
// this function call? Why did the programmer do this?
calc(int());
// some class that provides operator int()
convertible_to_int not_an_int;
// ...
calc(not_an_int);
// not_an_int is unchanged - is this really the intent?
// Did the programmer really want to write a do-nothing statement?
}
??? Obviously, you have narrowed your view to a particular class of functions.
because IMHO the restriction has been placed to prevent subtle bugs that
can only occur under very specific circumstances.
There is no problem with functions that take references to const - It
clearly states "dear function, take this object and do with it what you
like, but don't change it", whereas reference to non-const says "take
this object and do with it what you like; you may even change it".
In the latter case, the compiler cannot be sure if the programmer wanted
to modify a) the original object or b) the temporary object that had to
be created for conversion. These two things are completely different!