When can I be sure a constexpr global variable will be “forgotten”, like a C macro?

亡梦爱人 提交于 2020-02-02 12:24:26

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!