I think it would have been much better (and simpler for implementers!) if they had made std::exception a more fundamental part of the language and required that throw be used on a descendant of it. As it stands if you want to be sure to catch any failure from some external code you end up doing:
My personal opinion is that it's easier to deal with C++ exceptions (warts and all) than to try to avoid them. Just about any method that mutates a STL type can have a heap allocation fail and the only reasonable way to report that is via "throw std::bad_alloc();". Just make sure that your code always follows the principals of RAII ( http://en.wikipedia.org/wiki/RAII ) and you'll be fine.
Yes, throwing an arbitrary object as an exception is a humorously ridiculous approach.
It's as if every time a machine broke down in a factory, the workmen would have to wheel the machine into the manager's office, shove it on his desk and shout, "there, there's your problem!"... and if the manager didn't grab the machine, it would fly through his back window...