Ответ
На самом деле в код выше я упустил оператор delete[], поэтому в нем есть утечка памяти. Этого я не учел, так как на другом концентировался.
Моя ошибка, но соль примера была в другом. Поэтому сейчас будем разбирать такой код:
#include <iostream>
int main() {
auto array = new int[10, 20]{10};
std::cout << array[1, 0] << " " << array[11, 1] << std::endl;
delete[] array;
}
Такой код соберется выведет на консоль "10 0" и успешно завершится.
Но
то, что код успешно завершается не значит, что он понятен и работает, как мы ожидаем.
Основная загвоздка в том, что
в С++ запятая - это не просто знак препинания. Это оператор! У него есть вполне четкое и прописанное поведение -
он игнорирует результат любого выражения, кроме последнего.
То есть
Expression1, Expression2, Expression3
Все выражения вычислятся, но результатом комбинированного выражения будет результат Expression3.
Поэтому когда мы пишем [i, j] до с++23, то это полностью эквивалентно [j]. Компилятор видит несколько параметров в [] и, так как сам оператор индексации не принимает несколько параметров, то выход только один - парсить через оператор запятая.
Получается, что с помощью
new int[10, 20]
мы создали одномерный массив на 20 элементов.
Ну и вообще, весь код полностью эквивалентен следующему:
#include <iostream>
int main() {
auto array = new int[20]{10};
std::cout << array[0] << " " << array[1] << std::endl;
delete[] array;
}
На самом деле компилятор умеет выдавать предупреждения на использование оператора запятая. Поэтому использовании флагов компиляции -Werror -Wall, которые разрешают предупреждения и превращают их в ошибки компиляции, сборка упадет. Так что первый вариант ответа тоже был верным с какой-то стороны.
Теперь, почему
10 0
.
При аггрегированной инициализации мы можем в фигурных скобках указывать меньше элементов, чем может поместиться в массив или структуру. При этом остальные элементов будут инициализироваться так, как если бы они инициализировались от пустых скобок(аля array_elem = {};). Для интов это значит, что все элементы, кроме первого будут иметь нулевое значение.
То есть, никакого мусора. При использовании аггрегированной инициализации все поля будут иметь корректное и понятное значение.
Вот такая противная запятая.
Don't be confused. Stay cool.
#cpp23 #cppcore