Улучшение читаемости без потери производительности?

Давайте предположим, что у меня есть три функции f0, f1, f2 что все принимают три аргумента. Давайте также предположим, что у меня есть большая функция bigFunc вызвать, который принимает возвращаемые значения из первых трех функций в качестве аргументов.

Я могу хотеть сделать звонок как это:

bigFunc(f0(arg0, arg1, arg2), f1(arg3, arg4, arg5), f2(arg6, arg7, arg8));

Это большой вызов, поэтому я думаю, что было бы гораздо удобнее написать что-то вроде этого:

auto bigArg0 = f0(arg0, arg1, arg2);
auto bigArg1 = f1(arg3, arg4, arg5);
auto bigArg2 = f2(arg6, arg7, arg8);

bigFunc(bigArg0, bigArg1, bigArg2);

Это особенно здорово, если имена bigArg0, bigArg1, bigArg2 позвольте мне быть более конкретным о том, что я делаю (например, если f0, f1, f2 немного общего; Вы можете подумать об алгоритмах STL, которые делают разные вещи в зависимости от типа итераторов, которые вы ему предоставляете).

Однако проблема заключается в том, что bigArg0, bigArg1, bigArg2Я заставляю их больше не быть временными, что компилятору (я полагаю) труднее оптимизировать.

Вот мой вопрос: Как правильно это сделать, если я не хочу терять производительность? делать bigArg0, bigArg1, bigArg2 Const? Приведите аргументы bigFunc через std::move? Немного и того, и другого?

-1

Решение

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

Если они этого не делают, и у компилятора есть вся необходимая информация, чтобы доказать это, компилятор может свернуть копию без необходимости исключения RVO.

Возможно, это тот случай, если вы используете std::move? В любом случае перемещение может быть лучше, чем копирование …

Или возможно bigfunc получает свои аргументы с помощью константной ссылки, в этом случае оба пути приводят к одному и тому же коду в любом случае …

3

Другие решения

Вот решение, которое позволяет избежать именованных временных:

bigFunc(
f0(arg0, arg1, arg2),
f1(arg3, arg4, arg5),
f2(arg6, arg7, arg8)
);

Пример в увеличенном масштабе:

bigFunc(
f0(
f0_0(arg0, arg1, arg2),
f0_1(arg3, arg4, arg5),
f0_2(arg6, arg7, arg8)
),
f1(
f1_0(arg9, arg10, arg11),
f1_1(arg12, arg13, arg14),
f1_2(arg15, arg16, arg17)
),
f2(
f2_0(arg18, arg19, arg20),
f2_1(arg21, arg22, arg23),
f2_2(arg24, arg25, arg26)
)
);

Это обрабатывает 27 аргументов и 13 вызовов функций в 17 легко читаемых строках.

Это уже много дел в одном месте. К тому времени, когда это масштабируется настолько, что теряет читабельность, вы должны начать помещать его части в отдельные функции и / или объединять аргументы в структуры или классы.

1

По вопросам рекламы [email protected]