register
In C, the register storage class was used as a hint to the compiler, to express that a variable should be preferentially stored in a register. Note that the hint to store a register variable in an actual register may or may not be honored, but in either case the relevant restrictions still apply. See C11, 6.7.1p6 (emphasis mine):
A declaration of an identifier for an object with storage-class specifier
registersuggests that access to the object be as fast as possible. The extent to which such suggestions are effective is implementation-defined.[footnote 121][footnote 121] The implementation may treat any
registerdeclaration simply as anautodeclaration. However, whether or not addressable storage is actually used, the address of any part of an object declared with storage-class specifierregistercannot be computed, either explicitly (by use of the unary & operator as discussed in 6.5.3.2) or implicitly (by converting an array name to a pointer as discussed in 6.3.2.1). Thus, the only operators that can be applied to an array declared with storage-class specifierregisteraresizeofand_Alignof.
In C++ it is simply an unused reserved keyword, but it’s reasonable to assume that it was kept for syntactical compatibility with C code.
auto
In C, the auto storage class defines a variable of automatic storage, but it’s not usually used since function-local variables are auto by default.
Similarly, it’s reasonable to assume that it was initially carried over to C++ for syntactical compatibility only, although later it got its own meaning (type inference).