A shell is started when you login, but it's also started by programs like
make, or when you run a shell script, or when you type
vi, or when you create a new terminal window.
Originally, the shell read in
~/.profile when you logged in or ran
su. This script would do things like announce whether you had new email, customize your erase and kill characters, and set and export the TERM and PATH variables. When started in almost any other context, the shell did not read
~/.profile, because doing most of those things would be redundant. You were expected to have exported any important shell variables to the new shell.
The way the shell knew whether to read in
~/.profile was to check whether the first character of
csh, aliases were introduced. Aliases weren't exported in the environment.
csh was designed to read in two different initialization scripts.
~/.login was read only when a user logged in, and the cue to do this was if
argv began with
~/.cshrc was read every time the shell was started. In general, one placed aliases in
~/.cshrc and everything else in
csh also supported
~/.logout, which in most cases just cleared the screen and ran
Other shells adopted these same features.
ksh would read in
bash would read in
~/.bashrc, and those were where you'd place your alias definitions.
So, to make a long story short, the application that spawns a shell gets to decide whether it should be a "login shell", in which case there's that
'-' at the beginning, or a regular shell. In most cases, a shell that's going to be interactive is started as a login shell, and a shell meant just to run some commands, either as arguments or from a script, and then exit is a regular shell.
But it's all up to the whim of the application that starts the shell.