Примечания C ++: у Инициализации массива есть хороший список по инициализации массивов. у меня есть
int array[100] = {-1};
ожидая, что он будет заполнен -1, но его нет, только первое значение равно нулю, а остальные 0 смешаны со случайными значениями.
Код
int array[100] = {0};
работает просто отлично и устанавливает каждый элемент на 0.
Чего мне здесь не хватает .. Разве нельзя инициализировать его, если значение не равно нулю?
И 2: Происходит ли инициализация по умолчанию (как указано выше) быстрее, чем обычный цикл по всему массиву и присваивается значение, или она делает то же самое?
{0}
это не особый случай для структур и массивов. Правило состоит в том, что элементы без инициализатора инициализируются так, как если бы они были0
для инициализатора. Если есть вложенные агрегаты (напримерstruct x array[100]
), то инициализаторы применяются к неагрегатам в порядке "основной строки"; При этом фигурные скобки могут быть опущены.struct x array[100] = { 0 }
действует в C; и действует в C ++ до тех пор, пока первый членstruct X
принимает в0
качестве инициализатора.{ 0 }
не является особенным в C, но намного сложнее определить тип данных, который не может быть инициализирован с ним, так как нет конструкторов и, следовательно, нет способа остановить0
неявное преобразование и присвоение чему-либо .Ответы:
Используя синтаксис, который вы использовали,
говорит "установить первый элемент в,
-1
а остальные в0
", поскольку все пропущенные элементы установлены в0
.В C ++, чтобы установить их все
-1
, вы можете использовать что-то вродеstd::fill_n
(из<algorithm>
):В переносном C вы должны свернуть свой цикл. Существуют расширения компилятора, или вы можете полагаться на поведение, определяемое реализацией, в качестве ярлыка, если это приемлемо.
источник
#include <algorithm>
правильный заголовок,<vector>
может включать или не включать его косвенно, что будет зависеть от вашей реализации.int
s и развернуть ее в инициализаторе массива.fill_n
для заполнения всего 2D-массива. Вы должны пройти через одно измерение, заполняя другое.std::fill_n
это не инициализация.У компилятора gcc есть расширение, которое допускает синтаксис:
Это установит все элементы в -1.
Это известно как «Назначенные инициализаторы», смотрите здесь для получения дополнительной информации.
Обратите внимание, что это не реализовано для компилятора gcc c ++.
источник
Страница, на которую вы ссылаетесь, уже дала ответ на первую часть:
Не существует встроенного способа инициализации всего массива каким-либо ненулевым значением.
Что касается того, что быстрее, то применяется обычное правило: «Метод, который дает компилятору наибольшую свободу, вероятно, быстрее».
просто говорит компилятору «установить эти 100 дюймов на ноль», которые компилятор может свободно оптимизировать.
намного конкретнее. Он указывает компилятору создать переменную итерации
i
, сообщает ему порядок, в котором элементы должны быть инициализированы, и так далее. Конечно, компилятор, вероятно, оптимизирует это, но дело в том, что здесь вы чрезмерно уточняете проблему, заставляя компилятор работать усерднее, чтобы получить тот же результат.Наконец, если вы хотите установить для массива ненулевое значение, вы должны (по крайней мере, в C ++) использовать
std::fill
:Опять же, вы можете сделать то же самое с массивом, но это более кратко и дает компилятору больше свободы. Вы просто говорите, что хотите, чтобы весь массив был заполнен значением 42. Вы ничего не говорите о том, в каком порядке это должно быть сделано, или о чем-то еще.
источник
В C ++ 11 есть еще одна (несовершенная) опция:
источник
std::fill(begin(a), end(a), -1)
С помощью {} вы назначаете элементы так, как они объявлены; остальное инициализируется 0.
Если нет
= {}
инициализации, содержимое не определено.источник
На странице, на которую вы ссылались, указано
Проблема скорости: любые различия будут незначительными для таких маленьких массивов. Если вы работаете с большими массивами, а скорость гораздо важнее размера, вы можете получить массив const со значениями по умолчанию (инициализированными во время компиляции), а затем
memcpy
перевести их в модифицируемый массив.источник
Другим способом инициализации массива с общим значением будет создание списка элементов в последовательности определений:
Инициализация массива к общему значению может быть легко выполнена:
Примечание: DUPx введен для включения подстановки макросов в параметрах в DUP
источник
В случае массива однобайтовых элементов вы можете использовать memset, чтобы установить для всех элементов одинаковое значение.
Там пример здесь .
источник
Используя
std::array
, мы можем сделать это довольно простым способом в C ++ 14. Это можно сделать только в C ++ 11, но немного сложнее.Наш интерфейс имеет размер во время компиляции и значение по умолчанию.
Третья функция в основном для удобства, так что пользователю не нужно создавать
std::integral_constant<std::size_t, size>
себя, так как это довольно многословная конструкция. Настоящая работа выполняется одной из первых двух функций.Первая перегрузка довольно проста: она создает
std::array
размер 0. Нет необходимости в копировании, мы просто создаем его.Вторая перегрузка немного сложнее. Он продвигается вдоль значения, полученного в качестве источника, а также создает экземпляр
make_index_sequence
и просто вызывает некоторую другую функцию реализации. Как выглядит эта функция?Это создает первый аргумент размера - 1 путем копирования значения, которое мы передали. Здесь мы используем наши индексы пакета переменных параметров просто для расширения. В этом пакете есть записи размера - 1 (как мы указали в конструкции
make_index_sequence
), и они имеют значения 0, 1, 2, 3, ..., размер - 2. Однако нам нет дела до значений ( поэтому мы приводим его к void, чтобы заставить замолчать любые предупреждения компилятора). Расширение пакета параметров расширяет наш код до чего-то вроде этого (предполагая размер == 4):Мы используем эти скобки, чтобы гарантировать, что расширение пакета variadic
...
расширяет то, что мы хотим, а также чтобы убедиться, что мы используем оператор запятой. Без скобок было бы похоже, что мы передаем кучу аргументов в нашу инициализацию массива, но на самом деле мы оцениваем индекс, приводим его к void, игнорируем тот результат void, а затем возвращаем значение, которое копируется в массив ,Последний аргумент, который мы призываем
std::forward
, - это небольшая оптимизация. Если кто-то передает временную строку std :: string и говорит «создайте массив из 5 из них», мы бы хотели иметь 4 копии и 1 перемещение вместо 5 копий. Вstd::forward
гарантирует , что мы делаем это.Полный код, включая заголовки и некоторые модульные тесты:
источник
non_copyable
тип на самом деле копируется с помощьюoperator=
.non_copy_constructible
было бы более точное имя для объекта. Однако нигде в этом коде нет присваивания, поэтому для этого примера это не имеет значения.1) Когда вы используете инициализатор, для структуры или подобного массива, неопределенные значения создаются по умолчанию. В случае примитивного типа, такого как int, это означает, что они будут обнулены. Обратите внимание, что это применяется рекурсивно: у вас может быть массив структур, содержащих массивы, и если вы укажете только первое поле первой структуры, то все остальные будут инициализированы нулями и конструкторами по умолчанию.
2) Компилятор, вероятно, сгенерирует код инициализатора, который по крайней мере так же хорош, как вы могли бы сделать вручную. Я предпочитаю, чтобы компилятор делал инициализацию для меня, когда это возможно.
источник
В C ++ также возможно использование метапрограммирования и шаблонов с переменными значениями. Следующий пост показывает, как это сделать: Программно создавать статические массивы во время компиляции в C ++ .
источник
В языке программирования C ++ V4 Страуструп рекомендует использовать векторы или переменные над встроенными массивами. С valarrary, когда вы создаете их, вы можете инициировать их к определенному значению, например:
Инициализировать массив длиной 7 элементов с "7777777".
Это способ реализации ответа в C ++ с использованием структуры данных C ++ вместо «простого старого массива C».
Я переключился на использование valarray как попытку в своем коде попытаться использовать C ++ 'isms v. C'isms ....
источник
Должна быть стандартной функцией, но по какой-то причине она не включена ни в стандарт C, ни в C ++ ...
В Фортране вы можете сделать:
но у него нет чисел без знака ...
Почему C / C ++ не может просто реализовать это. Это действительно так сложно? Глупо писать это вручную, чтобы достичь того же результата ...
Что если это был массив из 1000,00 байтов? Мне нужно написать скрипт, чтобы написать его для меня, или прибегнуть к хакам со сборкой / и т.д. Это нонсенс.
Это совершенно портативно, нет причин не быть на языке.
Просто взломайте это как:
Один из способов взломать это с помощью предварительной обработки ... (Код ниже не охватывает крайние случаи, но написан, чтобы быстро продемонстрировать, что можно сделать.)
источник
memset
, даже с «жестко закодированным» массивом.