我试图了解数组如何在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的数组成员存储在自动存储中,但是大小是在运行时动态确定的?
由于
答案 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()调用的新函数中,然后您应该看到堆栈粉碎。