C++函数体内外的常量和聚合

Geo*_*nat 17 c++ compiler-errors compilation constants

考虑以下代码:

#include <iostream>
using namespace std;

int main()
{
    int x = 3;
    const int i[] = { 1, 2, 3, 4 };
    float f[i[3]]; 
    struct S { int i, j; };
    const S s[] = { { 1, 2 }, { 3, 4 } };
    double d[s[1].j];
}
Run Code Online (Sandbox Code Playgroud)

它运行没有错误.但是,以下内容:

#include <iostream>
using namespace std;


int x = 3;
const int i[] = { 1, 2, 3, 4 };
float f[i[3]]; // error: array bound is not an integer constant before ']' token|
struct S { int i, j; };
const S s[] = { { 1, 2 }, { 3, 4 } };
double d[s[1].j]; // error: array bound is not an integer constant before ']' token|

int main()
{
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

不会,因为它会将错误突出显示为注释.任何人都可以向我解释为什么会这样吗?

Nic*_*las 18

很可能,编译器在函数内允许它的原因是编译器扩展:可变长度数组.它们允许在函数内声明的数组具有非constexpr长度.但它只适用函数内部,而不适用于全局范围.


koc*_*ica 16

你必须使用constexpr而不是const

constexpr int i[] = { 1, 2, 3, 4 };
constexpr S s[] = { { 1, 2 }, { 3, 4 } };
Run Code Online (Sandbox Code Playgroud)

const 适用于变量,并防止在代码中修改它们.

constexpr告诉编译器这个表达式产生一个编译时常量值,因此可以在数组长度,分配给const变量等的地方使用它.

它在funcion中编译的原因是VLA.无法在全球范围内声明VLA.

6.7.6.2数组声明符

2如果标识符被声明为具有可变修改类型,则它应该是普通标识符(如6.2.3中所定义),没有链接,并且具有块范围或函数原型范围.如果标识符被声明为具有静态或线程存储持续时间的对象,则它不应具有可变长度数组类型.

此外,VLA不是标准的一部分,它是唯一的编译器扩展.

  • 虽然这是一个非常有效的解决方案,但它并不能解释编译器错误. (7认同)
  • 这不是因为在函数内部使用时,相同的构造工作. (2认同)