Я только начинаю изучать C ++ и хочу приобрести хорошие привычки. Если я только что выделил массив типа int
с new
оператором, как я могу инициализировать их все в 0, не просматривая их все самостоятельно? Должен ли я просто использовать memset
? Есть ли «С ++» способ сделать это?
176
&vector[0]
.Ответы:
Это удивительно малоизвестная особенность C ++ (о чем свидетельствует тот факт, что никто еще не дал это в качестве ответа), но на самом деле он имеет специальный синтаксис для инициализации значения массива:
Обратите внимание, что вы должны использовать пустые скобки - вы не можете, например, использовать
(0)
или что-либо еще (именно поэтому это полезно только для инициализации значения).Это явно разрешено ISO C ++ 03 5.3.4 [expr.new] / 15, который гласит:
и не ограничивает типы, для которых это разрешено, тогда как
(expression-list)
форма явно ограничена дополнительными правилами в том же разделе, так что она не допускает типы массивов.источник
new int[10] {}
. Вы также можетеnew int[10] {1,2,3}
Предполагая, что вы действительно хотите массив, а не std :: vector, «путь C ++» будет таким
Но имейте в виду, что под капотом это на самом деле просто цикл, который присваивает каждому элементу значение 0 (на самом деле другого способа сделать это нет, кроме специальной архитектуры с поддержкой аппаратного уровня).
источник
Существует множество методов для выделения массива внутреннего типа, и все эти методы являются правильными, хотя какой из них выбрать, зависит ...
Ручная инициализация всех элементов в цикле
Используя
std::memset
функцию из<cstring>
Используя
std::fill_n
алгоритм из<algorithm>
Использование
std::vector
контейнераЕсли доступен C ++ 0x , используйте функции списка инициализатора
источник
int array[SIZE] ={1,2,3,4,5,6,7};
нотацию, я могvoid rotateArray(int (& input)[SIZE], unsigned int k);
бы использовать объявление моей функции, что было бы при использовании первого соглашения? любое предложение?std::memset
неправильным - вы пропустили 10, похоже, ожидаемое количество байтов - см. En.cppreference.com/w/cpp/string/byte/memset . (Я думаю, это прекрасно показывает, почему следует избегать такой низкоуровневой конструкции, когда это возможно.)Если память, которую вы выделяете, является классом с конструктором, который делает что-то полезное, оператор new вызовет этот конструктор и оставит ваш объект инициализированным.
Но если вы выделяете POD или что-то, что не имеет конструктора, который инициализирует состояние объекта, то вы не можете выделить память и инициализировать эту память с помощью оператора new за одну операцию. Однако у вас есть несколько вариантов:
1) Вместо этого используйте переменную стека. Вы можете выделить и инициализировать по умолчанию за один шаг, например так:
2) использовать
memset()
. Обратите внимание, что если объект, который вы размещаете, не является POD , memsetting это плохая идея. Один конкретный пример: если вы устанавливаете класс с виртуальными функциями, вы уничтожите виртуальную таблицу и оставите свой объект в непригодном для использования состоянии.3) Многие операционные системы имеют вызовы, которые делают то, что вы хотите - выделить в куче и инициализировать данные для чего-то. Пример Windows будет
VirtualAlloc()
4) Обычно это лучший вариант. Избегайте необходимости самостоятельно управлять памятью. Вы можете использовать контейнеры STL для выполнения практически всего, что вы делаете с необработанной памятью, включая выделение и инициализацию всего одним махом:
источник
Да, есть:
Используйте вектор вместо динамически распределяемого массива. Преимущества включают в себя отсутствие необходимости явного удаления массива (он удаляется, когда вектор выходит из области видимости), а также то, что память автоматически удаляется, даже если возникает исключение.
Изменить: чтобы избежать дальнейших негативных отзывов от людей, которые не удосужились прочитать комментарии ниже, я должен пояснить, что этот ответ не говорит о том, что вектор всегда является правильным ответом. Но это, безусловно, более подход C ++, чем «ручная» проверка удаления массива.
Теперь с C ++ 11 есть также std :: array, который моделирует массив постоянного размера (против вектора, который может расти). Существует также std :: unique_ptr, который управляет динамически размещаемым массивом (который можно комбинировать с инициализацией, как и в других ответах на этот вопрос). Любой из них является более C ++ способом, чем ручная обработка указателя на массив, IMHO.
источник
std::vector
вместо динамически распределяемых массивов? Каковы преимущества использования массива над вектором, и наоборот?std::vector
.vector
везде независимо от контекста называется «Написание кода Java на C ++».std::fill
это один из способов. Принимает два итератора и значение для заполнения области. Это или цикл for (я полагаю) будет более подходящим для C ++.Специально для установки массива примитивных целочисленных типов в 0
memset
хорошо, хотя это может вызвать удивление. Учтите такжеcalloc
, что использовать C ++ из-за приведения немного неудобно.Со своей стороны, я почти всегда использую цикл.
(Я не люблю пересматривать намерения людей, но это правда, что при
std::vector
прочих равных условиях предпочтительнее использоватьnew[]
.)источник
Вы всегда можете использовать memset:
источник
memset
, но я не был уверен, что это был способ C ++ для решения этой проблемы.10 * sizeof( *myArray )
более документирован и защищен от изменений, чем10 * sizeof( int )
.Обычно для динамических списков элементов вы используете
std::vector
.Обычно я использую memset или цикл для динамического выделения памяти, в зависимости от того, какой переменной я ожидаю эту область кода в будущем.
источник