我编译并运行了以下C ++代码,盲目地尝试在C中创建一个灵活的数组成员:
#include <iostream>
template <typename T>
struct Vector {
int length;
T ts[];
};
Vector<int> ts = {
3,
{10, 10, 10},
};
int main() {
std::cout << sizeof(ts) << std::endl;
std::cout << ts.data[1] << std::endl;
return 0;
}
代码编译并运行得很好,并且在相同的情况下提供与C相同的输出(它输出4然后输出10)。
现在,根据this answer from 2010,我所写的内容不应该是有效的C ++。此外,根据this wikipedia article,&#34; C ++没有灵活的数组成员&#34;。
我的问题是,我在上面的代码中实际使用了哪种C ++功能,特别是在&#34; T ts[];
&#34;?该代码实际上是否按照我的想法执行,或者是未定义的行为?
答案 0 :(得分:1)
这是C和C ++之间不同的东西之一。 灵活数组成员在C中有效,但在C ++中无效。
也就是说,许多现代编译器将C编译为C ++的一个子集,只有在扭转编译器错误诊断时才注意。
David Tribble在他的Incompatibilities Between ISO C and ISO C++页面上花了一点时间,专门解决了这个问题:
C ++不支持灵活的数组成员。
(此功能可能由某些C ++编译器作为扩展提供,但可能仅对POD结构类型有效。)
是的,这是未定义的行为。编写这样一个东西的正确方法(在C和C ++中)是给它一个非零维度:
template <typename T>
struct Vector {
int length;
T ts[1];
};
您还有另一个问题:您必须为所述对象分配内存。仅指定初始化程序是不够的。只要存在对这种事物的每次访问,编译器只会认为它是最小的。
这个“范围黑客”之所以被称为是因为程序员明确地使用/滥用C(和C ++)的能力来违反范围界限以做一些棘手的事情。
这种情况的后果很多,包括无法将这些东西存储在任何标准容器中,或者按值传递它们,或者做大多数避免通过指针处理它的东西。它有它的位置,但对于绝大多数用例,C ++有更好的选择。