cat is not given a filename on the command line (or if the filename is just
-), then it switches to reading from its standard input.
That means that with
cat will notice that it was not given a filename and will proceed to read from the here-document, which is arriving on its standard input stream.
You can get
cat to read from both its standard input and from a file with
cat - filename <<END
This will cause the contents of the here-document to be concatenated with the contents of
filename. If the order of the arguments was
filename - then that would be the order that the data would be concatenated too.
- is not special to the shell in any way, and is interpreted as "standard input" specifically by the
cat utility (and a few others). If you have an actual file called
- that you need to run
cat on, use
cat ./-, i.e. specify the filename with a path.
For all purposes, you can think of feeding a here-document directly into a utility as a shorthand for creating a temporary file and then invoking the utility with that attached to the standard input stream:
printf 'some contents' >tmpfile
rm -f tmpfile
Here-documents might not actually be implemented this way (it may be a FIFO (named pipe)), but that's not an entirely incorrect way of thinking about it.
bash sources, it seems as if that particular shell implements here-documents by creating a temporary file using the
mkstemp() library function if it's available, otherwise it tries to create a random filename to write to. The contents of the document is then written to that file and the data is provided on the standard input of whatever it is that's reading it, just as if it came from a file, redirected with
lib/sh/tmpfile.c in the
bash source distribution.