没有给定维度的C ++ struct数组成员(灵活的数组成员?)

时间:2017-09-08 03:25:24

标签: c++ flexible-array-member

我编译并运行了以下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;?该代码实际上是否按照我的想法执行,或者是未定义的行为?

1 个答案:

答案 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 ++有更好的选择。