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

时间:2017-08-29 19:37:24

标签: 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];
}

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

#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;
}

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

2 个答案:

答案 0 :(得分:18)

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

答案 1 :(得分:16)

您必须使用constexpr代替const

constexpr int i[] = { 1, 2, 3, 4 };
constexpr S s[] = { { 1, 2 }, { 3, 4 } };

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

constexpr告诉编译器该表达式在编译时常量值中产生,因此可以在数组长度等地方使用,分配给const变量等。

它在funcion中编译的原因是VLA。无法在全球范围内宣布VLA。

6.7.6.2数组声明符

  

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

同样VLA不是标准的一部分,它是唯一的编译器扩展。