* Ivan Novick:
>> Alf P. Steinbach wrote:
>> #include <iostream> // std::cout
>> #include <ostream> // operator<<, std::endl
>> #include <vector> // std::vector
>>
>> int main()
>> {
>> using namespace std;
>> vector<double> d( 100 );
>>
>> d.at( 1 ) = d.at( 0 ) + 1;
>> cout << d.at( 1 ) << endl;
>> }
>>
>> Note everything in this program. 
> I'll bite. Can you please explain what you have done with this code?
> Especially the 3rd line in main?
Ah, yes. It wasn't meant as a mystery. The third line could have been
written as just
d[1] = d[0] + 1;
But in general, operator[] does no bounds checking, so if the indices
are out of bounds (i.e. negative or larger than the vector size) the
result is immediate C++ Undefined Behavior, which is difficult to detect
and debug because anything or nothing might happen.
'at' does bounds checking and throws an exception for out-of-bounds, and
is otherwise the same as operator[]; therefore recommended as default,
writing
d.at(1) = d.at(0) + 1;
unless profiling shows this to be a real bottlneck performancewise,
/and/ a reasonable proof that no out-of-bounds access happens, exists.
The immediate (possible) Undefined Behavior of operator[] is with 'at'
turned into a more well-behaved exception, which is more easily
detectable and easy to debug.
Since this program has no try-catch the formal C++ Undefined Behavior
again rears it ugly head (or would that be "behind"?) at a higher level
-- when the possible exception propagates out of 'main'.
Happily, on most C++ implementations an exception out of 'main' causes
well-defined /implementation defined/ behavior, which we usually call a
"crash"; again, easy to detect and debug. In practice it can be much
easier to detect and debug than if there is a try-catch in 'main'. On
the other hand, for a program distributed to end-users, the end-user
will not necessarily have a debugger or understand a core dump or
whatever a "crash" is on the end-user's machine, so for such a program
it should perhaps be written as
#include <cstddef> // EXIT_SUCCESS, EXIT_FAILURE
#include <stdexcept> // std::exception
...
int main()
{
using namespace std;
try
{
// Former contents of 'main', then
return EXIT_SUCCESS;
}
catch( std::exception const& x )
{
cerr << "!Sorry, I crashed (program failure)." << endl;
cerr << "!Technical info: " << x.what() << endl;
return EXIT_FAILURE;
}
}
And of course that construction can be written once and for all and
reused, just calling a 'cppMain' function (or whatever) from 'main'.
--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?