Replacement for deprecated register keyword C++ 11
We can find the rationale for deprecating register in defect report 809: Deprecation of the register keyword which says (emphasis mine):
The register keyword serves very little function, offering no more
than a hint that a note says is typically ignored. It should be
deprecated in this version of the standard, freeing the reserved name
up for use in a future standard, much like auto has been re-used this
time around for being similarly useless.
The removal of register for C++17 was approved in the Lenexa meeting but it is still reserved for future use.
The register keyword was deprecated in the 2011 C++ standard, as its
effect was already implicit in the language. It remains reserved for
future use by the standard, and is time to remove its vestigial
specification.
Because of the as-if rule the compiler only has to emulate the observable behavior of the program and therefore the optimizer can via the as-if rule choose to keep a variable in a register if it won't effect observable behavior and presumably will in most cases make better choices since it usually has more information.
For reference also see role of "register" C keyword? from the gcc
mailing list, one of the replies in the thread says:
I don't think the "register" keyword ever affected register allocation
in gcc. For that you have to go back to compilers of the 1970s.The register keyword does still have a use, though, in a gcc
extension: gcc uses it in combination with asm to implement register
variables.
What's wrong with register keyword in C++?
You've pretty much answered your own question:
I think modern compilers are very smart so they implicitly optimizes frequently used variables for speed (fast access) & puts them in CPU register.
That's precisely the point—optimisers are so good at register allocation nowadays that any attempt from the programmer to enforce their will through the register
keyword would likely lead to a pessimisatin, and is therefore simply ignored by the compiler. Remember that register
was never a binding requirement, always just a hint to the compiler. Now that they rightfully scoff at such hints, the keyword is simply obsolete and useless.
So, to directly answer your question of "what's wrong with it:" it no longer serves any purpose whatsoever, as the only one it ever had ("hint to the compiler to put this thing in a register") is now superseded by the compilers being way better at this than humans.
Is the register keyword still used?
Most implementations just ignore the register
keyword (unless it imposes a syntactical or semantical error).
The standard also doesn't say that anything must be kept in a register; merely that it's a hint to the implementation that the variable is going to be used very often. Its use is even deprecated.
7.1.1 Storage class specifiers [dcl.stc]
3) A register specifier is a hint to the implementation that the variable so declared will be heavily used. [ Note: The hint can be ignored and in most implementations it will be ignored if the address of the variable is taken. This use is deprecated (see D.2). — end note ]
Register keyword in C++
In C++ as it existed in 2010, any program which is valid that uses the keywords "auto" or "register" will be semantically identical to one with those keywords removed (unless they appear in stringized macros or other similar contexts). In that sense the keywords are useless for properly-compiling programs. On the other hand, the keywords might be useful in certain macro contexts to ensure that improper usage of a macro will cause a compile-time error rather than producing bogus code.
In C++11 and later versions of the language, the auto
keyword was re-purposed to act as a pseudo-type for objects which are initialized, which a compiler will automatically replace with the type of the initializing expression. Thus, in C++03, the declaration: auto int i=(unsigned char)5;
was equivalent to int i=5;
when used within a block context, and auto i=(unsigned char)5;
was a constraint violation. In C++11, auto int i=(unsigned char)5;
became a constraint violation while auto i=(unsigned char)5;
became equivalent to auto unsigned char i=5;
.
Why was the register keyword created?
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
register
suggests 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
register
declaration simply as anauto
declaration. However, whether or not addressable storage is actually used, the address of any part of an object declared with storage-class specifierregister
cannot 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 specifierregister
aresizeof
and_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).
Compiler behavior and register storage class specifier is deprecated
C++11, [dcl.stc]:
3 - A
register
specifier is a hint to the implementation that the variable so declared will be heavily used. [ Note: The hint can be ignored and in most implementations it will be ignored if the address of the variable
is taken. This use is deprecated (see D.2). — end note ]
There is a proposal to remove the register
keyword as a storage specifier, while reserving it as a keyword: Remove Deprecated Use of the register
Keyword (n4340). This may or may not be implemented in C++1z (tentative C++17); it would pose challenges for compatibility with C, where register
still has semantic effect (a C register
variable or parameter cannot have its address taken or be subject to array-to-pointer decay).
Turning off the 'register' storage class specifier is deprecated warning
In general, prepending no-
to an option turns it off. So if -Wdeprecated-register
enables the warning, then -Wno-deprecated-register
should disable it.
Alternatively, on many compilers you can use pragmas (or similar) in your code, to disable warnings while including particular headers while leaving them enabled for your own code. They are compiler-specific; for Clang, it's something like
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-register"
#include "dodgy.hpp"
#pragma clang diagnostic pop
(For GCC, the pragmas are the same, only replacing clang
with GCC
. I don't know about any other compilers.)
register keyword in C?
It's a hint to the compiler that the variable will be heavily used and that you recommend it be kept in a processor register if possible.
Most modern compilers do that automatically, and are better at picking them than us humans.
Related Topics
Long Long Int VS. Long Int VS. Int64_T in C++
Trivial VS. Standard Layout VS. Pod
Replacement for Deprecated Register Keyword C++ 11
Efficient Unsigned-To-Signed Cast Avoiding Implementation-Defined Behavior
May I Take the Address of the One-Past-The-End Element of an Array
What Does the "Lock" Instruction Mean in X86 Assembly
Using Regex Lookbehinds in C++11
When Do Extra Parentheses Have an Effect, Other Than on Operator Precedence
Is Auto as a Parameter in a Regular Function a Gcc 4.9 Extension
Extract Year/Month/Day etc. from Std::Chrono::Time_Point in C++
What Is the Purpose of Allocating a Specific Amount of Memory for Arrays in C++
How Std::Bind Works with Member Functions
Should We Pass a Shared_Ptr by Reference or by Value
How Would You Implement Your Own Reader/Writer Lock in C++11
C++ Auto Keyword. Why Is It Magic
Std::Transform() and Toupper(), No Matching Function
How to Convert Std::Chrono::Time_Point to Calendar Datetime String with Fractional Seconds