Подтвердить что ты не робот

Почему вы не можете опустить размер массива в новый инициализатор?

Это разрешено:

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
4b9b3361

Ответ 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};