问题
I want to use a global constexpr
variable:
constexpr int foo = 123;
instead of a C macro:
#define FOO (123)
in some code I'm writing. I would like to be guaranteed the same behavior, in the sense that this will not take up space in memory at runtime, nor will it be visible/exist in the compiled object code (that is, its value will be used as an immediate where relevant).
Can I get this guarantee at all? Under some conditions? Assume, of course, I'm not trying to use x's address or any such funny business.
回答1:
The C++ standard does not make any guarantees about taking space in memory at runtime, or the contents of object files.
constexpr int foo = 123;
at namespace scope means that foo
has internal linkage, and in each translation unit that this line is visible, there is an object with static storage duration, of sizeof(int)
bytes.
The compiler is permitted, but not required, to optimize out this storage if the output of the program does not depend on whether the storage actually exists. (This is called the as-if rule).
An example of where the storage probably would not be optimized out would be if you had a function:
int const *bar() { return &foo; }
In practice:
- it is very likely that if
foo
is not odr-used then it will not occupy memory at runtime. - it is very likely that
foo
's name will not appear in an object file, since it has internal linkage.
回答2:
Can I get this guarantee at all? Under some conditions? Assume, of course, I'm not trying to use x's address or any such funny business.
Yes, the compiler will almost always substitute foo
for the number at compile time with no extra memory See constexpr.
Almost certainly, the compiler will only allocate memory to foo
if you take it's address.
And, from the link on ([expr.const])... we see a note:
Note: Constant expressions can be evaluated during translation.
And, and as far as most C++ compilers I know goes, they will evaluate and fold expressions where possible.
Using gcc.godbolt.org, this code (without taking the address of foo
)...
constexpr int foo = 123;
int x(){
int b = 5 + foo;
return b;
}
Without optimization flags, the Code generated was:
x():
movl $128, %eax
ret
=======================================
But this code... (taking the address of foo
)
constexpr int foo = 123;
int x(){
int b = 5 + reinterpret_cast<long>(&foo);
return b;
}
generated....
x():
movq foo, -8(%rsp)
movl foo, %eax
addl $5, %eax
ret
foo:
.long 123
NB: Why I have used may instead if will is because the C++ standard doesn't force compilers to do so, (but they almost certainly do so, some are free not to do so for their specific constraints).
回答3:
I would like to be guaranteed the same behavior, in the sense that this will not take up space in memory at runtime, nor will it be visible/exist in the compiled object code (that is, its value will be used as an immediate where relevant).
constexpr int foo = 123;
will be equally seen as 123
whenever the compiler hits it. No extra memory, nothing fancy.
So yes, it's completely equivalent with the preprocessors replacement for
#define FOO (123)
来源:https://stackoverflow.com/questions/36990014/when-can-i-be-sure-a-constexpr-global-variable-will-be-forgotten-like-a-c-mac