函数中的Const数组与静态Const数组
const array vs static const array in a function
例如,有一个函数做某事。我应该如何声明和定义一个数组内的函数,我想被分配/初始化只有一次?
void someclass::somefunction(/*parameters here*/)
{
static const my_array[4] = {1,2,3,4}; // #1
/*or just*/
const my_array[4] = {1,2,3,4}; // #2
}
据我所知,在#1的情况下,"my_array"将在数据段中分配,并在"somefunction"调用的第一次初始化。但是我的一个同事做了一个假设,情况#2以同样的方式工作,没有必要写"static"关键字。
所以我想问的是标准是否对情况有规定#1 ,如果有,具体是什么?我应该如何定义这种类型的数组,以确保它将被分配/初始化只有一次?
谢谢。
编译器将为这两个选项生成相同的代码。
您的示例非常简单,因为该数组涉及纯旧数据(POD)。标准规定,每次运行somefunction
时,选项1将被初始化,但第一次运行somefunction
时,选项2将被初始化。然而,只要结果与标准中指定的结果无法区分,实现是允许偏离的,即所谓的as-if规则。
在这种情况下,编译器将数组写入可执行文件的只读内存,并且在运行时根本没有初始化。他们可以使用POD类型。
如果你有一个需要运行时实例化的对象,那么事情就不同了。考虑下面程序的行为:
class MyObject
{
public:
MyObject() {}
};
void f()
{
const MyObject arr1[1] = { MyObject() };
static const MyObject arr2[1] = { MyObject() };
}
int main(int argc, char* argv[])
{
f();
f();
return 0;
}
MyObject
的构造函数运行3次
我的编译器(gcc 4.4.3
)在这两种情况下生成相同的代码。
void f()
{
static const my_array[4] = {1,2,3,4}; // #1
}
void g()
{
const my_array[4] = {1,2,3,4}; // #2
}
结果程序集:
f:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
leave
ret
.cfi_endproc
g:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
movq %rsp, %rbp
.cfi_offset 6, -16
.cfi_def_cfa_register 6
leave
ret
.cfi_endproc
.section .rodata
.align 16
.type my_array.1594, @object
.size my_array.1594, 16
my_array.1594:
.long 1
.long 2
.long 3
.long 4
.align 16
.type my_array.1591, @object
.size my_array.1591, 16
my_array.1591:
.long 1
.long 2
.long 3
.long 4
我不知道其他编译器是否以同样的方式运行
以最符合逻辑和最清晰的方式声明和定义它,只有当分析显示它是一个瓶颈时,我才会建议更改代码。
在这种情况下,一些编译器很可能生成相同的代码。由于初始化语义略有不同,其他代码可能会产生不同的代码(例如,在某些情况下,g++使用互斥锁保护静态值的初始化)。