Член массива структуры C ++ без заданного измерения (гибкий член массива?)

Я скомпилировал и запустил следующий код 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).

Теперь согласно этот ответ от 2010 то, что я написал, не должно быть верным C ++. Кроме того, согласно эта статья в википедии, Msgstr «C ++ не имеет гибких членов массива».

Мой вопрос заключается в том, какую функцию C ++ я на самом деле использую в приведенном выше коде, особенно в строке, которая говорит:T ts[];Msgstr «Этот код на самом деле делает то, что я думаю, он делает в целом, или это неопределенное поведение?

0

Решение

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

Тем не менее, многие современные компиляторы компилируют C как подмножество C ++, заботясь только о том, чтобы ускорить диагностику ошибок компилятора.

Дэвид Триббл тратит на это момент на своем Несовместимость между ISO C и ISO C ++ страница, где он конкретно решает эту проблему:

C ++ не поддерживает гибкие члены массива.

(Эта функция может быть предоставлена ​​как расширение некоторыми компиляторами C ++, но, вероятно, будет действительной только для структурных типов POD.)

Так что да, это неопределенное поведение. Правильный способ (как на C, так и на C ++) написать такую ​​вещь — дать ей ненулевое измерение:

template <typename T>
struct Vector {
int length;
T ts[1];
};

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

это «Дальний взлом» это так называется, потому что программист явно использует / использует способность C (и C ++) нарушать границы диапазона, чтобы сделать что-то хитрое.

Последствия этого многочисленны, в том числе невозможность хранить эти вещи в любом стандартном контейнере, передавать их по значению или делать все, что угодно, избегая обработки через указатель. Он имеет свое место, но для подавляющего большинства случаев использования C ++ имеет превосходные варианты.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]