(Standardese) 数组大小技术问题

问题描述 投票:0回答:1

我们知道一个数组的大小一定是一个

constant expression
。 我们也知道
constant expression
可以在编译时求值,但不能保证它会在编译时求值。

所以现在......假设

foo()
可用作常量表达式: 如果编译器(无论出于何种原因,真的)在这个假设的场景中没有在编译时评估
foo()
调用,会发生什么?数组将如何“初始化”?这会是 VLA 的情况吗?或者它会被认为是“未知边界的数组”?

int myArray[foo()]; // assume the compiler doesn't evaluate foo() at compile time, because it's not mandatory...?

编辑:看这个例子:


constexpr int foo() {
    // constexpr: CAN be evaluated at compile time
    // Not mandatory for it to BE evaluated at compile time (??)
    return 5;
    // A conforming compiler might still decide to evaluate this at run-time, no?

}

int main() {
    // A compiler might decide to NOT evaluate foo() at compile time
    // So what...?
    int myArray[foo()];
};
c++ arrays standards
1个回答
1
投票

写作时

int myArray[foo()];

这是声明具有已知边界的数组的语法形式。标准规定在这样的声明中用于数组大小的表达式必须是一个 converted constant expression of type

std::size_t
.

如果不是这样的常量表达式,那么程序是病式的。该标准要求编译器发出诊断,并且不需要任何关于此类程序行为的其他信息。

如果是这样的常量表达式,则指定声明将

myArray
声明为大小为X
int
array类型的对象,其中
X
foo()
的(转换)值。

标准的其余部分描述了给定大小的数组的行为方式,例如如何访问索引

0
X-1
处的元素,它们的
sizeof
X
等等。编译器必须确保执行程序的行为符合根据这些规则的标准描述。

这就是常量表达式的全部含义。实施不需要其他任何东西。

如何指定数组的方式意味着如果编译器想要有效地实现数组,它实际上需要知道常量表达式

foo()
的值。例如,否则它将无法在堆栈上保留足够的内存,否则将需要做一些低效的事情,例如使用运行时计算值调用
alloca
。编译器没有理由要这样做。

另外,因为编译器需要诊断

foo()
是否是常量表达式,这本身就有效地需要对表达式进行全面评估,如果编译器不存储计算值而不是在运行时重新计算它来实现,那将是愚蠢的一些不寻常的低效形式或数组。

归根结底,数组的正常实现,数组的大小根本不是运行时存在的量。数组的大小始终由其声明中的常量表达式固定。在格式良好的 C++ 程序中,同一个数组声明不能有两种不同的大小。因此,在实现中保持变量也是没有意义的。

此外,标准 C++ 中没有 VLA,并且声明不使用未绑定数组的形式,因此两者都不是。它只是一个大小为

5
.

的数组的声明
© www.soinside.com 2019 - 2024. All rights reserved.