0xb*_*00d 9 c++ arrays standards
我在一个我必须维护的项目中发现了一段奇怪的代码.有一个类的空数组成员,不会导致编译器错误.我已经使用MSVC 10.0测试了这些代码的一些变体:
template<class T> struct A {
int i[];
}; // warning C4200: nonstandard extension used : zero-sized array in struct/union
template<class T> struct B { static int i[]; };
template<class T> int B<T>::i[];
struct C {
int i[];
}; //warning C4200: nonstandard extension used : zero-sized array in struct/union
template<class T> struct D { static int i[]; };
template<class T> int D<T>::i[4];
template<> int D<int>::i[] = { 1 };
int main()
{
A<void> a;
B<void> b;
C c;
D<void> d0;
D<int> d1;
a.i[0] = 0; // warning C4739: reference to variable 'a' exceeds its storage space
b.i[0] = 0; // warning C4789: destination of memory copy is too small
c.i[0] = 0; // warning C4739: reference to variable 'c' exceeds its storage space
int i[]; // error C2133: 'i' : unknown size
d0.i[0] = 0; // ok
d0.i[1] = 0; // ok
return 0;
}
Run Code Online (Sandbox Code Playgroud)
错误消息int i[]对我来说绝对明智.用类显示的代码D是格式良好的标准C++.但这些课程是什么A,B并且C?int i[]这个类中的成员变量是什么类型的?
编辑:
你的疑问是通过语言扩展的定义来解释的,它允许在结构/联合结束时使用零大小的数组.我没有尝试过,但如果你在零大小的数组后声明另一个成员,它应该失败.
所以,如果你在堆栈上分配一个变量,你必须知道它的大小; 规则的例外是在struct/union的末尾分配一个数组,其中一些C典型的技巧是可能的.
在c ++中,这会引发警告,因为默认的复制构造函数和赋值运算符可能不起作用.
以前的答案:
编译器警告您,您正在尝试定义零大小的数组.标准C/C++中不允许这样做.
让我们逐类看到差异.
在D级:
template<class T> struct D { static int i[]; };
它的工作原理是因为你只是声明一个静态成员变量的类型.要进行链接,您还需要在定义语句中定义实际数组,如下所示:
template<> int D<int>::i[] = { 1 };
Run Code Online (Sandbox Code Playgroud)
在这里,您还可以通过初始化程序指定数组的大小.
对于B类,您正在做类似的事情,但定义是:
template<class T> int B<T>::i[];
Run Code Online (Sandbox Code Playgroud)
即,您没有指定大小并获得警告.
对于类A,更多相同,您正在定义类型为array的成员变量,而不是大小.