声明没有大小的数组数据成员

时间:2014-10-28 17:14:16

标签: c++ arrays

我试图了解数组如何在C ++中运行。关于SO的一些好线程,但我有一个我无法找到答案的问题是:

为什么可以声明没有大小的数组数据成员?我认为在C ++中,数组大小必须是编译时常量?

示例:

#include<iostream>

class Object{

public:
      Object(std::size_t n){  

        for(std::size_t i = 0; i<n; ++i) { array[i] ='X'; }

        //prints 0 because 'sizeof' is compile-time operator
        std::cout << "compile-time size: " << sizeof(array) << std::endl;
        std::cout << "run-time size " << n << std::endl;
      }

private:
      char array[];
};  

int main( int argc, char** argv )
{
  Object obj(10);      //10 chars

  std::size_t n;
  std::cin >> n;
  Object obj2(n);      //n chars in automatic storage i.e. on the stack??
}

Input: 
  n = 1000
Output: 
  compile-time size: 0
  run-time size 10
  compile-time size: 0
  run-time size 1000

这是否意味着obj2的数组成员存储在自动存储中,但是大小是在运行时动态确定的?

由于

5 个答案:

答案 0 :(得分:4)

  

为什么可以声明没有大小的数组数据成员?

在标准C ++中,它不是。在C中,您可以在结构的末尾添加一个,以允许可变大小的数组 - 但您必须确保为您想要使用的任何大小分配足够的存储空间。某些C ++编译器可能允许将其作为非标准扩展。

  

这是否意味着obj2的数组成员存储在自动存储中,但是大小是在运行时动态确定的?

不,这意味着阵列没有任何存储空间,而且您正在写入堆栈的其他部分。这不是一个好主意。

如果您需要动态数组,请使用std::vector

答案 1 :(得分:2)

根据C ++标准(9.2级成员)

  

9 非静态(9.4)数据成员不应具有不完整类型。在   特别是,C类不应包含类的非静态成员   C,但它可以包含指向C类对象的指针或引用。

因此它是编译器功能或其错误。

作为类的非静态数据成员的数组存储在分配该类的相应对象的位置。

对于C,C允许定义结构的灵活数组成员。

来自C标准(6.7.2.1结构和联合说明符)

  

18作为特例,结构的最后一个元素超过   一个命名成员可能具有不完整的数组类型;这叫做a   灵活的阵列成员

但在这种情况下,结构应具有多个命名成员

答案 2 :(得分:1)

C99允许使用名为灵活数组成员的功能。这在C11标准的第6.7.2.1 / 18节中描述:

  

作为一种特殊情况,结构的最后一个元素有多个   命名成员可能具有不完整的数组类型;这叫做a   灵活的阵列成员。在大多数情况下,灵活的阵列成员   被忽略了。

它们不是C ++的一部分,但有些编译器允许将它们用作扩展。例如,GCC在其C扩展页面上明确指出了这一点:

  

ISO C99中的一些功能,但不是C90或C ++,也是如此   扩展,GCC在C90模式和C ++中接受。

为了兼容性,Clang通常实现GNU扩展。请注意,在所述成员上使用sizeof似乎是GCC错误或扩展名:

  

灵活的数组成员具有不完整的类型,因此sizeof   可能无法应用运算符。作为原始实现的怪癖   对于零长度数组,sizeof的计算结果为零。

此外,灵活的数组成员是类中唯一的数据成员是GNU扩展。

答案 3 :(得分:0)

没办法。 char array [] 与指向char的指针相同。这意味着你可以做到这一点。

char* pointer;
char array[];
array=pointer;

指针有值,当指针创建时,它在内存中。只需将某处指向记忆即可 数组的工作方式与指针相同。如果 int 有4字节, array [5] 指向指针的字节后的int 5 * 4 = 20。

int array[];
array[5];
*(array+5);

C ++在穿过数组后不会抛出异常。通常是程序崩溃,因为默认情况下指针指向程序中的某个内存。

答案 4 :(得分:0)

将测试移动到从main()调用的新函数中,然后您应该看到堆栈粉碎。