In short:
- Undefined behaviour: this is not okay to do
- Unspecified behaviour: this is okay to do, but the result could be anything*
- Implementation-defined behaviour: this is okay to do, the result could be anything* but the compiler manual should tell you
Or, in quotes from the C++ standard (N4659 section 3, Terms and Definitions):
3.28 Undefined behavior: behavior for which this International Standard imposes no requirements
3.29 Unspecified behavior: behavior, for a well-formed program construct and correct data, that depends on the implementation
3.12 Implementation-defined behavior: behavior, for a well-formed program construct and correct data, that depends on the implementation and
that each implementation documents
EDIT: *As pointed out by M.M in the comments, saying that the result of unspecified behaviour could be anything is not quite right. In fact as the standard itself points out, in a note for paragraph 3.29
The range of possible behaviors is usually delineated by this International Standard.
So in practise you have some idea of what the possible results are, but what exactly will happen depends on your compiler/compiler flags/platform/etc.