Почему вы не можете опустить размер массива в новый инициализатор?
Это разрешено:
int a[]{1, 2, 3};
Но не это:
auto a = new int[]{1, 2, 3};
Вы должны указать границы. Почему?
EDIT: правильный синтаксис (который не компилируется):
auto a = new (int[]){1, 2, 3};
Это дает реальное сообщение об ошибке:
error: invalid use of array with unspecified bounds
Ответы
Ответ 1
Ответ MSalters указывает, почему это не было изменено в последних версиях стандарта. Здесь я отвечу на вопрос компаньона: "Где в стандарте С++ 11 это запрещено?"
Относительно new (int[]){1, 2, 3}
Во-первых, мы должны отметить, что int[]
является неполным типом.
... массив неизвестного размера... - это не полностью определенный тип объекта. - [basic.types] §3.9 ¶5
Наконец, отметим, что оператор new
не позволяет указанному типу быть неполным:
Этот тип должен быть полным типом объекта... - [expr.new] §5.3.4 ¶1
В стандарте нет ничего, чтобы сделать исключение для этого случая, когда используется синтаксис braced-init-list.
Относительно new int[]{1, 2, 3}
int[]
в этом случае анализируется с использованием создания типа new-type, в котором используется noptr-new-declarator production для разбора квадратных скобок:
noptr новый-описатель:
[выражение] attribute-specifier-seq opt
noptr-new-declarator [константное выражение] attribute-specifier-seq opt
Обратите внимание, что выражение не помечено как необязательное, поэтому этот синтаксис просто не разбирается.
Ответ 2
Как уже отмечал Джонатан Вакели в комментариях, на самом деле это закрытый вопрос. Решение "должно быть обработано в рабочей группе по эволюции" по существу означает, что РГ21 считает, что это не плохая идея сама по себе, но в то же время они не считают ее дефектом в нынешнем стандарте. Что имеет смысл - там нет намека на то, что должно работать, это просто по аналогии.
Ответ 3
Я думаю, что это потому, что компилятор читает файлы в последовательном методе, он никогда не возвращается, (поэтому вы должны использовать, например, форвардные объявления, а не просто ждать, пока функция будет объявлена позже). Я не уверен, что это официальная причина, но это имеет смысл для меня.
Это мое объяснение:
Строка int Array[]={1,2,3};
может обрабатываться последовательным образом следующим образом:
start array: поместите 1 в 1-ое место, поместите 2 во 2-й, поместите три в 3-й конец массива, поэтому: размер массива 3 целых числа, поэтому переместите кадр стека на этот размер.
Но следующая строка: int *p=new int[]{1,2,3};
должна начинаться с выделения памяти, помимо размещения элементов в памяти и определения размера. Как это можно сделать последовательным образом?
Чтобы разрешить что-то подобное, вы должны нарушить принцип последовательности и начать обработку с конца, а затем вернуться, чтобы вызвать соответствующий размер распределения.
EDIT:
В ответ на 1-й комментарий
Я сделал несколько тестов в следующем коде:
class A{
public:
A(){
err2 error;
cout<<sizeof(A)<<endl;
}
err1 error;
};
компилятор, похоже, оставляет встроенные функции компилируемыми, как будто они появляются после класса.
Доказательством является то, что независимо от порядка, ошибки членов обнаруживаются до ошибок функции.
Поэтому в классе образца я получаю err1 error
до err2 error
, хотя хронологический порядок противоположный.
Поэтому я считаю, что классы являются исключительными, в противном случае в классе функции были очень ограниченными в использовании самого класса.
EDIT2:
int Array[]={sizeof(Array)};
дает ошибку, единственная причина - размер массива задается после закрытия массива. он больше похож на проблему в вопросе, чем int Array[]={1,2};