常量变量的存储分配
Storage allocation to const variables
我正在读一本书,其中提到了这个
如果编译器知道 const 的每次使用,则无需分配 容纳它的空间。例如:
const int c1=1;
const int c3=my_f(3);
extern const int c4;
鉴于 c3 和 c4 的值不称为编译时,存储 必须为 C3 和 C4 分配。
我对此一无所知。我的疑问是:
抱在这里是什么意思?它是否仍然需要将所有内容存储在内存中?对于 c1,我们没有任何存储分配吗?
请消除我的疑虑。
谢谢。
c1
与其他两个常量的不同之处在于它是用文字值初始化的。这允许编译器将该值放在使用常量的任何位置,如下所示:
int x = z + c1;
可以替换为
int x = z + 1;
这意味着编译器不需要在其中分配空间和存储1
。
c3
和c4
是不同的:一个是使用函数计算的,另一个是从不同的编译单元提供的。这意味着编译器不能再像c1
那样执行替换:编译器不知道c3
和c4
的值。因此,编译器生成代码
int x = z + c4;
就像c4
是存储在内存中某个位置的变量一样。由于在这种情况下c4
是一个外部常量,链接器将解析其位置,并填写编译器缺少的信息(即c4
的地址(,以使程序完成并准备好运行。
Const 有 2 种用途 - 替换宏(常量表达式(和不可变数据。
此声明:
const int c1=1;
本质上是此的类型安全版本:
#define c1 1
这样,这段代码:
int foo = c1;
可以简单地编译为:
int foo = 1;
哪个更有效率。
另一方面,这:
const int c3=my_f(3);
用作不可变的 c3。它可能存在于内存中,但您无法修改它。它本质上是int c3=my_f(3);
更安全的版本。
为了说明这一点:
int a1[c1];
int a2[c3];
A1 是有效的,因为编译器可以将 A1 推导出为常量表达式。 A2 不是,因为虽然 C3 是 const,但在编译时可能不知道。
C++11 添加了与 const
类似的 constexpr
关键字,但比 const
更严格。只有c1
和c2
才能constexpr
. c3
也可能是,尽管它要求my_f
也是。
作为积分常量表达式,编译器完全有权使用常量折叠将其从程序中删除。只有当你拿它的地址时,这才不正确。此外,如果可能的话,现代优化编译器可以使用 LTO、内联和常量折叠来对 c3 和 c4 执行相同的操作。
如果不获取变量的地址,则编译器没有义务根据 as-if 规则生成具有等效结果的代码,则编译器没有义务分配该变量。
编辑:常量折叠是编译器在编译时而不是运行时计算表达式的地方。例如,您可以合法地执行在编译时计算3 + 4
int x[3 + 4];
。一些例子,特别是那些涉及内燃机的例子,是标准规定的,但如果可能的话,实施可以执行更多。LTO 是链接时间优化,当翻译单元链接在一起时,编译器会跨翻译单元执行优化。
这意味着编译器可以内联 my_f
的主体,然后(取决于主体(常量折叠它以使其成为常量表达式c3
,然后常量将其折叠到使用它的地方而不分配它。对于c4
,LTO可能会产生c4
的值作为常量表达式,在这种情况下,它也可以被常量折叠和删除。
在C++11中,有constexpr
功能允许在该地区做更多工作。
- 存储在堆分配向量中的指针的免费存储
- 如何为静态常量模板化专用整数值分配存储
- 是否可以仅通过将分配的指针地址存储在C++中来分析内存?
- C++ 将抽象类型的动态分配对象传递给函数并存储在向量中
- 具有对齐存储的动态内存分配
- shared_ptr的删除程序是否存储在自定义分配器分配的内存中?
- C++标准对局部变量的存储和分配有什么保证?
- 将 C 样式字符串复制到免费存储上分配的内存中
- 未存储分配的数据
- 存储数据列表并自动分配给结构的最佳方法是什么
- 在未分配某些元素的数组中存储了什么值
- 在类存储结构中使用动态分配的数组
- 动态分配存储数据在堆中的随机位置中
- 当分配动态内存以存储字符串副本时,程序会中断
- 我可以在不手动将它们分配在堆上的情况下存储iostreams集合
- 为什么使用预留分配存储后不能迭代和打印矢量的内容?
- 在调用解构之后,存储在内存中的动态分配值会发生什么变化
- C++为对象分配存储而不对其进行初始化
- 使用指针为文件C++中的数字动态分配存储
- 为构造函数中的结构数组分配存储C++