int and const int in C++
当我问到C ++中int和const有什么区别吗?
有人这样说。
An int can be modified when you need, it is read/write and a const int is read only.(can change dynamically). You can use a const int for something like fixed value, and const int memory usage is less than normal int.
真正的const int内存使用量是否小于普通int。 在C ++中?
-
一般来说,没有。 它仍然需要存储在某个地方。
-
优化器可以很好地避免将常量存储在数据空间中,而是在已知该值的情况下将其硬编码为直接参数。 但是随后常数出现在程序空间中。 它可能会在多个位置复制,并且实际的全局内存使用量会更大。
-
@YvesDaoust:在C ++中,它甚至不需要优化程序就可以做到; 在C ++中可以保证。 复制它不会增加代码的大小,因为直接指令参数比从内存中获取值到寄存器并传递寄存器参数或将地址参数传递给指令便宜。 也需要更少的CPU周期。
-
不管是否声明了变量const,编译器都可以选择将变量存储为寄存器。 因此,在两种情况下都可能没有为int分配内存。
-
据我所知avr-g ++不使用程序存储器来存储const
可能会或可能不会,取决于使用方式。大多数编译器非常聪明,它们不需要为const对象创建存储。因此,例如:
1 2 3 4 5
| void f() {
const int arr_size = 10;
int arr[arr_size];
// do something with arr
} |
在这里,arr_size的唯一用途是指定数组的大小。无需为此创建一个int对象。编译器仅创建一个大小为10的数组。
另一方面有:
1 2 3 4 5 6 7 8 9
| void f(const int* ip) {
// do something with ip
}
int main() {
const int n = 100;
f(&n);
return 0;
} |
在这里,编译器必须为n创建一个int对象,因为代码采用的地址为n。
-
我认为如果f不执行任何操作,仍可以对其进行优化。
-
编译器可以内联函数,因此不需要地址。自己检查一下。在这里,编译器仅将100加载到寄存器中,然后直接调用printf()。
-
@ zett42-我真的不想下去寻找防弹插图的棘手问题。您明白了那个例子,不是吗?
-
@GillBates-f会做一些事情。阅读评论!
-
反汇编证明您的语句编译器必须为n创建一个int对象,因为代码采用n的地址。是错的。在这种情况下,是否采用"地址"与编译器无关。如果编译器选择内联函数调用,则地址运算符会被优化。比较本示例中我删除了const和地址的反汇编。编译器为main()函数创建相同的程序集。
-
@ zett42:您的示例反汇编应演示什么,我们将其与之进行比较?它不使用n的地址,并且您已经定义了一个函数f(int),而在这里它是f(int*)-这具有重要的区别。内联可能会有所作为,但这是编译器要解决的问题,并且不受语言标准的保证,因此此处的要点几乎不会失效。
在C ++中,除非使用const变量的地址,否则将其视为文字常量,并将其插入到代码中,就好像其值是按字面值输入的一样。也就是说:
1 2
| const int BUFFLEN = 16 ;
char buffer[BUFFLEN] ; |
将生成与以下代码相同的代码:
const BUFFLEN在内存映射中不作为单独的对象存在,除非明确引用其地址,例如:
1
| printf("%p", &BUFFLEN ) ; |
假设未引用其地址,则生成的代码将比其存在于特定地址中的代码小,并且每次使用时都必须将其提取并加载到寄存器中。
此外,R / W存储器中不必存在非常量int,但是如果它具有常量初始化程序,则该初始化值也必须存在于代码空间中。因此,例如:
将消耗RAM中的空间,还将初始化值存储在ROM中(对于Arduino)(在Arduino的情况下),该值在启动时复制到RAM之前,主要或任何全局静态对象构造函数中。
因此,是的,const确实有可能比非常量消耗更少的资源。但是我想这是const语义的副作用,而不是其目的。
-
除非采用const变量地址,否则将其视为文字常量-即使采用该地址,编译器也可以优化指针,并将变量仍存储在寄存器中。请参阅此拆卸。在第5行中,编译器将文字100加载到寄存器esi中,该寄存器随后将传递给printf()。只有当您实际打印出地址时,编译器才真正必须分配存储空间,就像在反汇编中一样。
-
@ zett42:公平的观点,尽管我不认为这通常会使答案无效。我已经稍微修改了答案。请注意,打印出该地址并不一定要强制其进行存储-只需要将其作为函数参数传递,而不必将该函数内联。
常量是使变量不可分配的意思。防止违反预期的约束是一种高水平的事情。您不会注意到任何影响,除非是实际常数。 (在这里我建议使用constexpr代替)
这会影响记忆力吗?不,仅添加const不会更改int(或任何其他类)的任何内容。
这将有助于优化吗?不,编译器足够聪明,可以在没有常量的情况下自行推断出常量。
为什么要使用它?要强制执行A??PI,请说明意图...
-
您的前两个句子是矛盾的。
-
我试图表达自己更好一点,还是不清楚?
-
好吧,第一句话不再像使用某种内存控制工具一样显示const,但是现在它错误地将const限制为防止赋值,这仅适用于原始类型(并且仅当您看到其他修改操作,例如++作为"分配")。当涉及到更高级别的类型时,我们要处理更抽象的规则:const变量意味着只能在其上调用非const成员函数。 C ++甚至允许您将operator=重载为const操作,尽管那将是可怕的编码风格:)
使用相同数量的内存,因为它们都分配int的大小。使用const的唯一原因当然是为不会改变的特定引脚或值定义一个常数。 int可以读写,const int只能读取。 const int节省空间的原因是因为编译器对待的是不会改变的值,因此它不会进行任何允许其修改值的调整,从而节省了内存。