Ваше понимание немного ошибочно. Алмазный оператор - хорошая функция, так как вам не нужно повторять себя. Имеет смысл определить тип один раз, когда вы объявляете тип, но просто не имеет смысла определять его снова с правой стороны. Принцип DRY.
Теперь, чтобы объяснить весь пух об определении типов. Вы правы, что тип удаляется во время выполнения, но как только вы хотите извлечь что-то из списка с определением типа, вы возвращаете его как тип, который вы определили при объявлении списка, иначе он потеряет все определенные функции и будет иметь только Объектные функции, за исключением случаев, когда вы отбрасываете извлеченный объект к его исходному типу, который иногда может быть очень сложным и приводит к исключению ClassCastException.
Использование List<String> list = new LinkedList()
будет получать предупреждения rawtype.
Обратите внимание, что для memset вы должны передавать количество байтов, а не количество элементов, потому что это старая функция C:
memset(d, 0, sizeof(double)*length);
memset can будет быстрее, поскольку он написан на ассемблере, тогда как std :: fill
- это шаблонная функция, которая просто выполняет внутренний цикл.
Но для обеспечения безопасности типов и более читаемого кода я бы рекомендовал std :: fill ()
- это способ работы c ++, и рассмотрите memset
, если в этом месте кода требуется оптимизация производительности.
Я думаю, вы имеете в виду
memset(d, 0, length * sizeof(d[0]))
и
for (int i = length; --i >= 0; ) d[i] = 0;
Лично я использую любой из них, но полагаю, что std :: fill ()
, вероятно, лучше.
В качестве альтернативы всем предлагаемым вещам я могу предложить вам НЕ устанавливать массив на все нули при запуске. Вместо этого устанавливайте нулевое значение только тогда, когда вы впервые обращаетесь к значению в определенной ячейке. Это избавит вас от вопросов и может быть быстрее.
Я могу предложить вам НЕ устанавливать массив на все нули при запуске. Вместо этого устанавливайте нулевое значение только тогда, когда вы впервые обращаетесь к значению в определенной ячейке. Это позволит избежать вашего вопроса и может быть быстрее. Я могу предложить вам НЕ устанавливать массив на все нули при запуске. Вместо этого устанавливайте нулевое значение только тогда, когда вы впервые обращаетесь к значению в определенной ячейке. Это позволит избежать вашего вопроса и может быть быстрее.Если вам требуется не использовать STL ...
double aValues [10];
ZeroMemory (aValues, sizeof(aValues));
ZeroMemory по крайней мере проясняет намерение.
В общем, memset будет намного быстрее, убедитесь, что вы правильно указали длину, очевидно, ваша В примере (m) не выделен или не определен массив значений типа double. Теперь, если он действительно закончится лишь несколькими дублями, цикл может оказаться быстрее. Но когда мы дойдем до точки, когда цикл заполнения будет затенять, несколько инструкций по настройке memset обычно будут использовать более крупные и иногда выровненные фрагменты для максимизации скорости.
Как обычно, тестируйте и измеряйте. (хотя в этом случае вы попадаете в кеш и измерение может оказаться подделкой).
memset (d, 10, 0) неверен, поскольку он обнуляет только 10 байтов. предпочитайте std :: fill, поскольку цель наиболее ясна.
Не забудьте сравнить правильно оптимизированный цикл for, если вы действительно заботитесь о производительности.
Некоторые варианты устройства Даффа, если массив достаточно длинный, и префикс --i без суффикса i-- (хотя большинство компиляторов, вероятно, исправят это автоматически.)
Хотя я бы сомневался, является ли это наиболее ценным для оптимизации. Действительно ли это узкое место для системы?
В дополнение к нескольким ошибкам и упущениям в вашем коде, использование memset не переносимо. Вы не можете предположить, что двойное значение со всеми нулевыми битами равно 0,0. Сначала исправьте код, а затем подумайте об оптимизации.
calloc(length, sizeof(double))
Согласно IEEE-754, битовое представление положительного нуля - это все нулевые биты, и нет ничего плохого в том, чтобы требовать соответствия IEEE-754. (Если вам нужно обнулить массив для его повторного использования, выберите одно из вышеперечисленных решений).
memset(d,0,10*sizeof(*d));
скорее всего будет быстрее. Как говорится, вы тоже можете
std::fill_n(d,10,0.);
, но, скорее всего, это более красивый способ сделать цикл.
Попробуйте это, хотя бы для того, чтобы быть крутым xD
{
double *to = d;
int n=(length+7)/8;
switch(length%8){
case 0: do{ *to++ = 0.0;
case 7: *to++ = 0.0;
case 6: *to++ = 0.0;
case 5: *to++ = 0.0;
case 4: *to++ = 0.0;
case 3: *to++ = 0.0;
case 2: *to++ = 0.0;
case 1: *to++ = 0.0;
}while(--n>0);
}
}
Если вам действительно все равно, вы должны попробовать и измерить. Однако наиболее переносимым способом является использование std :: fill ():
std::fill( array, array + numberOfElements, 0.0 );
Согласно этой статье Википедии о IEEE 754-1975 64-битной с плавающей запятой битовая комбинация всех нулей действительно правильно инициализирует двойное значение 0,0. К сожалению, ваш код memset этого не делает.
Вот код, который вы должны использовать:
memset(d, 0, length * sizeof(double));
Как часть более полного пакета ...
{
double *d;
int length = 10;
d = malloc(sizeof(d[0]) * length);
memset(d, 0, length * sizeof(d[0]));
}
Конечно, это отбрасывает проверку ошибок, вы должны быть выполнение по возвращаемому значению malloc. sizeof (d [0])
немного лучше, чем sizeof (double)
, потому что он устойчив к изменениям типа d.
Также, если вы используете calloc (length, sizeof (d [0]))
он очистит память для вас, и последующий memset больше не понадобится. Я не использовал его в примере, потому что тогда кажется, что на ваш вопрос не будет ответа.
Пример не будет работать, потому что вам нужно выделить память для вашего массива. Вы можете сделать это в стеке или в куче.
Это пример того, как сделать это в стеке:
double d[50] = {0.0};
После этого memset не требуется.
Если длина цикла является целочисленным постоянным выражением, наиболее вероятным результатом будет то, что хороший оптимизатор распознает как цикл for, так и memset (0). В результате сгенерированная сборка будет практически одинаковой. Возможно, выбор регистров может отличаться или настройка. Но предельные затраты на удвоение действительно должны быть одинаковыми.