Массив переменных размеров как член класса: почему он компилируется?

у меня есть эта ситуация, которую я не могу объяснить, почему она компилируется:

#include <iostream>
using namespace std;

class X {
public:
    X() {cout << "in X constructor: " << endl;};
};

class Y {
public:
    Y() {cout << "in Y constructor" << endl;};
private:    
    X x[];
};

int main() {
    Y y;
    return 0;
}

Я определяю массив переменного размера X как член класса Y. Определение X Это такой способ вне класса, безусловно, приведет к ошибке компиляции, но не внутри класса. Более того, конструктор X никогда не вызывается.

так что же здесь происходит?

1 ответов


C99, 6.7.2.1 / 16 (n1256)

как частный случай, последний элемент структуры с более чем одним именем члена может иметь неполный тип массива; это называется гибкий элемент массива. В большинстве ситуаций, гибкий элемент массива игнорируется. В частности, размер структуры как бы гибкий элемент массива был опущен, за исключением того, что он может иметь больше завершающего заполнения, чем опущение будет предполагать.

это не массив переменной длины. Это не что-то вроде члена данных, скорее интерфейс, чтобы сообщить компилятору, что вы можете получить доступ к некоторой памяти через имя гибкого члена массива.

/17

пример после объявления:

struct s { int n; double d[]; };

структура struct s имеет гибкую член массива d. Типичный способ использовать это:

int m = /* some value */;
struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));

и предполагая, что вызов malloc завершается успешно, объект, на который указывает p в большинстве случаев ведет себя так, словно p было объявлено как:

struct { int n; double d[m]; } *p;

это не разрешено в C++11, но принято g++ и clang++ в качестве расширения. Поскольку количество элементов не известно конструктору struct (для C++), конструктор может инициализировать эти элементы (автоматически).