具有常量对象的代码大小
Code size with const objects
我有几个源文件,其中需要一些const
变量。
在提供的框架中,有一个.hpp头文件,其中包含这些变量的定义(不仅是声明),并且此标头包含在我前面提到的源文件中。
然后我意识到,我的每个源文件都包含该 RO 数据const
变量的副本,因此为了减少内存占用(我正在开发 ebdedded 系统),我又制作了一个 .hpp,它包含在我的源文件中,其中包含对这些变量的extern
引用(包含在其他地方)。
我比较了构建 .o 对象信息,发现当将 .hpp 与 extern 引用一起使用时,代码大小和 RO 数据大小更大,而不是与实际变量的定义一起使用。
为什么?
更新:我犯了错误。具体来说,这里是链接器映射文件的片段: (注:RW,ZI删除)
不使用外部
:代码:1192
(包括数据):84 RO数据:144
使用外部:代码:1392
(包括数据):216
RO数据:
144
但我的错误有更多的新问题而不是答案:
- 在这种情况下,为什么 RO(常量数据)大小没有改变?
- 此范围内的公司数据是什么?
当定义未extern
时,编译器可以内联它们,因此它们直接存储在代码中的"立即加载"指令中。
(这称为"恒定折叠"。
使它们extern
对编译器隐藏了定义,迫使它在编译期间存储值并生成代码以在运行时获取它们。
它们不存储在只读段中,因为它们需要在程序启动时初始化,因此必须是可写的。
只读段仅适用于永不更改的内容,例如字符串文本的内容。
基本类型且C++中没有外部链接的常量没有存储或地址,除非获取其地址。 相反,文本值将插入到代码中,就像键入其数值一样。 例如代码:
const NUM = 25 ;
int n1 = NUM ;
int n2 = NUM ;
将生成相同的代码,以:
int n1 - 25 ;
int n2 = 25 ;
这是因为插入文本值所需的指令比从只读内存复制该值所需的指令更少。
但是,如果您有代码:
const NUM = 25 ;
int* np = &NUM ;
那么NUM
将被迫拥有存储。
当您将 const 声明为外部时,您是在说该值存在于其他位置,并且链接器将分配它。 编译器无法知道如果在单独的模块中定义它将具有的值,并且它无法知道其他模块是否会获取其地址,因此必须显式存储它 - 这使得只读数据空间更大,但也使代码空间更大。
虽然在函数或类作用域之外的常量变量C++具有隐式静态链接,但在 C 中,它们是隐式extern
。 因此,您可能会发现,如果使用 C 编译,结果会有所不同。 对于互操作性,如果您在头文件中声明 const,那么明智的做法可能是static
显式声明它,以确保两种语言的语义相同。
- 为什么我们不在下面给出的代码中使用指针来实例化C++的实体对象?
- 如果 iostream 对象不可复制,为什么以下代码是合法的?
- 使用 gtest 框架在单元测试代码中检查目标对象的私有变量的最佳实践是什么?
- 创建跨平台 C++ 触摸管理器.在 c++ 中传递 Objective-c 对象涉及代码
- 由于缺少类模板,NVCC 编译面向对象代码时出现问题
- 使用 jni 将返回带有模板的对象的 Java 代码转换为 c++
- 在 C++ 对象包装器中安全地包含 C 代码
- 在C++代码中搜索对象的实例化位置
- 使用.natvis文件可视化VS代码中的C++对象
- C++指向对象的指针堆数组中,如何将字符串传递给特定对象?有一些代码请看一下:
- C++ 被此代码与多态性、指针和对象切片混淆
- 从本机代码返回到托管代码会损坏返回的对象
- 如果用户尝试从 JS 调用对象的未定义函数C++则回调C++代码
- 在 boost::p ython 中的 python 对象中运行 python 代码
- 初始化不可移动对象数组:为什么这样的代码无法在 GCC 上编译?
- 一般函数中类的概括为基类创建对象代码
- C++模板的对象代码是否在可执行文件和动态库中重复?
- 我不想导出的函数的未记录代码对象警告
- 代码对象和可执行文件的区别
- 如何保持作为 SWIG shared_ptr传递给非托管代码的托管代码对象的活动状态?