c++中的数值常数
Numerical constant in C++
我看到很多关于静态const、#define和enum之间应该选择哪一个的问题。
没有讨论在嵌入式系统中很重要的资源方面。
我不喜欢使用#define
,但它不像static
那样消耗资源。关于enum
,在消耗RAMROM吗?
此外,我被告知,如果我使用例如const int
,它将不会消耗RAM或ROM,假设我不使用指针引用这个变量。这是真的吗?
如果这是真的,为了节省资源,在namespace
中使用const int
不是一个很好的解决方案吗?
备注:我使用的是c++ 2003标准,不能使用2011标准。(我已经看到enum class
和constexpr在2011年,但我不能使用它们)
…如果我使用例如
const int
,它将不会消耗RAM或ROM, 假设我不使用指针引用到此变量
。如果使用#define
或enum
,编译器没有理由将常量放入数据内存中——它总是将其放入代码中。如果你使用const int
,编译器只会在你的代码没有引用它(即当它没有使用odr时)时才会做同样的事情。
有一些看起来很友好的结构,它们默默地将引用引入到您的代码中,因此在实践中,您不能假设const int
的行为方式与enum
相同。例如:
const int UNIVERSE = 42;
int calc = ...;
int answer = max(calc, UNIVERSE);
如果您从std
名称空间使用max
(就像您应该的那样),它将在您的代码中引入const
对UNIVERSE
的引用,这可能将42添加到您的数据ROM中。也
:
bool condition = ...;
int answer = condition ? 0 : UNIVERSE;
这里也有同样的问题(详见这里);您的代码可能在const int
上的行为与#define
或enum
中的任何一个都不同。
c++ 11引入了constexpr
,它将避免这些微妙的问题。因此,如果您不能使用c++ 11并希望获得最大性能(或最小内存浪费),则应该使用#define
或enum
。此外,如果您希望常量的类型不是int
,则必须使用#define
:
#define UNIVERSE (uint64_t)42
你的假设毫无意义。所有的数据都必须存储在某个地方。你不能在空气中存储数据。
#define
和const
的区别在于前者倾向于将常量嵌入到代码内存中,而后者可能会在数据内存中为变量提供专用地址。在任何一种情况下,它们都将消耗相同数量的内存量。
如果你不启用任何编译器优化,然而,在数据内存中存储在专用地址的变量可能会导致内存消耗的微小变化,如果在这种情况下,获取数据的指令也可能包含原始值。
但是这些微优化不是你应该考虑的。我们说的是ROM存储器,你应该有足够的ROM存储器。
在固定地址上分配这些常量的优点是,您可以获取它们的地址并在调试器中查看它们的值。所以它们不一定与#defined
相同。
程序不使用的变量将被优化掉。
类型的定义本身不消耗内存(ROM);除了调试信息(如果有的话)。
所以简单;
enum MyValues {
Value1,
Value2
};
不会占用ROM,但是,该类型的实例化(实际对象)会占用内存(先从ROM加载,然后再从RAM加载)。
MyValues val1 = Value1;
上面,val1
占用内存
那么与#define
或const int
替代方案有什么区别呢?
清晰。
预处理器(使用#define
)和编译器(使用const int
)足够聪明,在大多数情况下可以做几乎完全相同的事情(除了获取const int
的地址之类的事情)。enum
是将相关值组合在一起的语言结构,它不是唯一的,但它是一个非常自然的结构。
- 为什么 g++ 使用 movabs 和一个奇怪的常数来简单还原?
- 为什么在C++负数static_cast如果<unsigned>数字是常数,则不同
- 表达式必须具有常数值,变量不能用作定义数组大小的常数
- 变量和常数的C++划分不起作用
- 我应该将乘数声明为常数还是直接使用它而不声明?
- 按常数偏移折线
- 如何在 C 和 C++ 中定义字符常数?
- 在CUDA内核中传递一个常数整数
- 如何使用常数向量访问成员函数
- 定义.cpp中常数int/char*
- 阵列 C 中的常数表达
- 我是否应该避免在循环中的常数之间进行操作
- 为什么我可以更改指针的常数(const char *)槽的值
- C++ 乘法 256 * 256 * 256 * 256 = 0? 积分常数溢流 C4307
- 如何接受用户输入以进行常数并使用writeProcessMemory
- 表达式未评估为常数两个级别的constexpr函数(编译器错误?)
- 使变量成为常数的重要性是什么?
- 错误:数字常数之前的预期无限制ID:std :: array和std ::向量大小分配
- 正在使用C 三元运算符中的字符串常数,一种无效的非效率数组的使用
- 如果我的源文件中使用常数,则如何使编译很好地停止