когда (не) хранить часть вложенной структуры данных во временной переменной - довольно / некрасиво, быстрее / медленнее? - PullRequest
1 голос
/ 06 января 2012

Как лучше всего читать несколько чисел / строк в одном массиве / структуре / объединении, которое само вложено в один или несколько родительских массивов / структур / объединений?

1-й пример без временной переменной:

printf("%d %d\n", a[9][3], a[9][4]);

1-й пример с временной переменной:

int *b = a[9];
printf("%d %d\n", b[3], b[4]);

Я уверен, что временная переменная в первом примере выше довольно глупа, но во втором примере ниже она имеет смысл и выглядит лучшеиспользовать один, верно?

2-й пример без временной переменной:

foo[i]->bar.red[j][0]++;
foo[i]->bar.red[j][1]++;
foo[i]->bar.red[j][2]++;
foo[i]->bar.red[j][3]++;

2-й пример с временной переменной:

int *p = foo[i]->bar.red[j];
p[0]++;
p[1]++;
p[2]++;
p[3]++;

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

Ответы [ 3 ]

3 голосов
/ 06 января 2012

Во-первых, я считаю, что это просто вопрос читаемости / удобства сопровождения кода, то есть индивидуального предпочтения.Компиляторы умнее нас сегодня (шутка).: -)

Лично я обычно думаю о том, чтобы извлечь временную переменную (или функцию, это относится и к ним) в двух случаях:

  • Когда можно назвать ее так, чтобыего имя говорит само за себя и говорит больше, чем начальное выражение, или
  • Если мне придется повторить какой-то фрагмент кода хотя бы три раза .

Таким образом, ваш первый пример я бы оставил так:

printf("%d %d\n", a[9][3], a[9][4]);

А второй будет:

int *p = foo[i]->bar.red[j];
p[0]++;
// ...

Или (часто, но не всегда)) лучше:

int *bar_red = foo[i]->bar.red[j];
bar_red[0]++;
// ...
2 голосов
/ 06 января 2012

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

Во втором примере это приведет к:

/*previous code
...
*/
int *quadruplet = foo[i]->bar.red[j];
{ /*intentionaly meaningless braces that prepare the introduction 
  of a function (incrementQuadruplet) in a later refactoring if needed*/
  quadruplet[0]++;
  quadruplet[1]++;
  quadruplet[2]++;
  quadruplet[3]++;
}
/*following code
...
*/
1 голос
/ 06 января 2012

Это не дает точного ответа на ваш вопрос, но я не могу не подчеркнуть это, поскольку большинство программистов попадают в ловушку слишком часто.

Практическое правило: Избегайте преждевременных оптимизаций.
Современные дневные компиляторы достаточно умны, чтобы самостоятельно выполнять тривиальные оптимизации.
Напишите код, который легко понять, поддерживать и который соответствует стандартам / методам кодирования команды, в которой вы работаете.
Получите вашу работу правильно в соответствии с требованием, Профилируйте свой код для бутылочных горлышек и только затем попытайтесь оптимизировать код, который, как оказывается, является горлышком бутылки.

...