最接近初始化而不是检查的方法是使用const
对数组的引用,然后在全局对象中初始化该数组。它仍然是运行时初始化,但不知道你是如何使用它的,所以这可能已经足够好了。
#include <cstring>
enum {A, B, C, COUNT};
namespace {
class ArrayHolder {
public:
int array[COUNT]; // internal array
ArrayHolder () {
// initialize to all -1s
memset(this->array, -1, sizeof(this->array));
}
};
const ArrayHolder array_holder; // static global container for the array
}
const int (&arr)[COUNT] = array_holder.array; // reference to array initailized
// by ArrayHolder constructor
您仍然可以sizeof
像以前一样使用它:
for (size_t i=0; i < sizeof(arr)/sizeof(arr[0]); ++i) {
// do something with arr[i]
}
编辑
如果永远不能依赖运行时初始化,则应检查 asm 中的实现详细信息,因为arr
即使使用初始化程序声明的值在运行时初始化之前仍可能未知
const int arr[1] = {5};
int main() {
int local_array[arr[0]]; // use arr value as length
return 0;
}
编译g++ -pedantic
给出警告:
warning: ISO C++ forbids variable length array ‘local_array’ [-Wvla]
编译实际失败的另一个示例:
const int arr1[1] = {5};
int arr2[arr1[0]];
error: array bound is not an integer constant before ']' token
至于使用数组值作为全局构造函数的参数,这里的构造函数调用都很好:
// [...ArrayHolder definition here...]
class IntegerWrapper{
public:
int value;
IntegerWrapper(int i) : value(i) {}
};
const int (&arr)[COUNT] = array_holder.array;
const int arr1[1] = {5};
IntegerWrapper iw1(arr1[0]); //using = {5}
IntegerWrapper iw2(arr[0]); //using const reference
此外,未定义跨不同源文件的全局变量的初始化顺序,您不能保证arr = {-1, -1, -1};
直到运行时才会发生。如果编译器正在优化初始化,那么您依赖的是implementation,而不是标准。
我在这里真正要强调的一点是:int arr[COUNT] = {-1, -1, -1};
除非可以优化,否则仍然是运行时初始化。您可以依靠它保持不变的唯一方法是使用 C++11 constexpr
,但您没有可用的。