Почему разница между int a [5] = {0} и int a [5] = {1} (отсутствующая функция) [закрыто

StackOverflow https://stackoverflow.com/questions/4772680

Вопрос

Когда мы инициализируем такой массив int a[5] = {0}, компилятор делает все 5 элементов 0. Это действительно хорошо, компактная инициализация и полезная функция.

Но мне интересно, почему компилятор не инициализируется int a[5]={1} по аналогии? Почему это не делает все 5 элементов 1? Почему стандарт не требует этого? Разве это не было потрясающей функцией? Разве это не отсутствует?

Кроме того, если количество элементов в инициализаторе меньше размера массива, то компиляция может инициализировать оставшиеся элементы с последним элементом в инициализаторе. Означает, int a[5]={1,2,3} эквивалентно int a[5]={1,2,3,3,3}. Анкет И аналогично, int a[10]={1,2,3,0} эквивалентно int a[10]={1,2,3,0,0,0,0,0,0,0};.

Разве это не было бы потрясающей функцией, если стандартный мандат? Или есть веские причины для этой недостающей функции?


И есть что -то называемое Указанный инициализатор в C99, который используется как:

Определенные инициализаторы могут быть объединены с обычными инициализаторами, как в следующем примере:

int a[10] = {2, 4, [8]=9, 10}

В этом примере [0] инициализируется до 2,1 инициализируется до 4, A [2] к [7] инициализируется до 0, а [9] инициализируется до 10.

Довольно интересно. Но даже эта функция не в C ++.

Это было полезно?

Решение

Я лично нахожу более «логичный» (т.е. просто) с фиксированным инициализатором по умолчанию вместо другого правила повторения последнего только для массивов. Это может показаться «практичным» (то есть полезно), но это IMO более логически сложно.

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

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

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

Есть места C ++, где вы будете сильно страдать, если попытаетесь использовать логику вместо учебы. Просто назвать несколько...

  • Почему по умолчанию статичны (т.е. неправильный)?
  • Почему нет ключевого слова для нулевого указателя?
  • Почему разница в двух без подписи не вписывается?
  • Почему сумма между подписанным и без подписи не подписана?
  • Если не знакомы со стороны «элемента Z_ {2^n}"Тогда почему размеры без подписи?
  • Почему std::string s; s=3.141592654; Совершенно верный C ++?
  • Почему в C ++ 0x i = i++ + 1; является неопределенным поведением и i = ++i + 1; является действительным?
  • Почему double x=3.14; int y(int(x)); не значит y будет 3?

Другие советы

Почему это не делает все 5 элементов 1?

Потому что вы неправильно понимаете, что {} означает. (На самом деле, в C ++ лучший способ сделать это {} скорее, чем {0}) Синтаксис {0} не означает, что вы хотите, чтобы все элементы в совокупности были установлены на ноль. Скорее, в нем говорится, что вам нужен заполнитель с первым нулевым элементом, назначенным указанной переменной (которая может быть либо массивом, либо типом класса в C ++). Поскольку совокупность обычно имеет больше полей, чем у одного значения нулевым, оставшиеся элементы в совокупности по умолчанию построено. Анкет Значение по умолчанию типа встроенного или стручка состоит в том, чтобы установить все поля на ноль, чтобы вы эффективно установили весь агрегат на ноль.

Что касается того, почему конкретно рассмотрим следующее. Согласно текущему стандарту, ни одно из приведенных ниже утверждений не удастся:

struct abc
{
    char field1;
    int field2;
    char field3;
};

int main()
{
    abc example = {'a', static_cast<int>('b')};
    //All three asserts pass
    assert(example.field1 == 'a');
    assert(example.field2 == static_cast<int>('b'));
    assert(example.field3 == '\0');

    int example2[3] = {static_cast<int>('a'), 42};
    assert(example2[0] == static_cast<int>('a'));
    assert(example2[1] == 42);
    assert(example2[2] == 0);
}

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


РЕДАКТИРОВАТЬ: Только что понял, что ваш вопрос задается с точки зрения массивов - но ответ одинаковы либо со структурами, либо с массивами, так что это действительно не имеет значения.

Edit2: Чтобы сделать это больше в соответствии со стандартом, ссылки на класс/структуру были заменены «заполнителем» ниже, что охватывает структуры и массивы.

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

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

Типичные библиотеки времени выполнения предоставляют функцию, которая облегчает инициализацию данных в 0. В общих чертах, это хранится в конкретном раздел в исполняемом файле, организованном компилятором и линкером. При запуске программы код запуска выполнения использует что -то вроде memset() Чтобы очистить все инициализированные данные до 0. Это означает, что нулевые байты не должны храниться внутри самого исполняемого файла.

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

Поэтому, если бы вы объявили большой множество char (Скажите мегабайт?) И инициализируйте его, скажем, {0}, Тогда в исполняемом файле не было бы байтов, хранящихся для этого массива. С другой стороны, если бы вы инициализировали его с {1} под вашей схемой, мегабайт 1 Байты должны были бы храниться в самом исполнении. Изменив один символ в списке инициализатора, размер исполняемого увеличения на мегабайт.

Я считаю, что такая схема нарушит Принцип наименее сюрприза.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top