Крайне важно, чтобы сгенерированный код был максимально эффективным.
blockquote>Еще одно замечание, касающееся вашего примера: вы должны убедиться, что производительность не страдает от передачи аргументов функции по значению. То же самое для возвращаемого значения.
Есть ли способ сделать это, избегая как переменных времени выполнения, так и вспомогательной функции?
blockquote>Вы можете реализовать вспомогательные функции многократного использования. В качестве примера рассмотрим следующий код.
static_assert(__cplusplus >= 201703L, "example written for C++17 or later"); #include <cstddef> #include <array> #include <type_traits> #include <utility> namespace detail { template<std::size_t... inds, class F> constexpr void gen_inds_impl(std::index_sequence<inds...>, F&& f) { f(std::integral_constant<std::size_t, inds>{}...); } }// detail template<std::size_t N, class F> constexpr void gen_inds(F&& f) { detail::gen_inds_impl(std::make_index_sequence<N>{}, std::forward<F>(f)); } // the code above is reusable template< std::size_t... inds_out, class T, std::size_t size_out, std::size_t size_in > constexpr std::array<T, size_out> insert1( std::array<T, size_out> out, std::array<T, size_in> in ) { static_assert((... && (inds_out < size_out))); static_assert(sizeof...(inds_out) <= size_in); gen_inds<sizeof...(inds_out)>([&] (auto... inds_in) { ((out[inds_out] = in[inds_in]), ...); }); return out; }
Аналогичной альтернативой является
static_for
подход:static_assert(__cplusplus >= 201703L, "example written for C++17 or later"); #include <cstddef> #include <array> #include <type_traits> #include <utility> namespace detail { template<std::size_t... inds, class F> constexpr void static_for_impl(std::index_sequence<inds...>, F&& f) { (f(std::integral_constant<std::size_t, inds>{}), ...); } }// detail template<std::size_t N, class F> constexpr void static_for(F&& f) { detail::static_for_impl(std::make_index_sequence<N>{}, std::forward<F>(f)); } // the code above is reusable template< std::size_t... inds_out, class T, std::size_t size_out, std::size_t size_in > constexpr std::array<T, size_out> insert2( std::array<T, size_out> out, std::array<T, size_in> in ) { static_assert(sizeof...(inds_out) >= 1); static_assert((... && (inds_out < size_out))); static_assert(sizeof...(inds_out) <= size_in); constexpr std::size_t N = sizeof...(inds_out); static_for<N>([&] (auto n) { // note the constexpr constexpr std::size_t ind_out = std::array{inds_out...}[n]; constexpr std::size_t ind_in = n; out[ind_out] = in[ind_in]; }); return out; }
Я имею статья об этой самой теме . Таким образом (скопированный с конца страницы):
Вот мое эмпирическое правило:
StringBuilder
лучше всего используется, когда точное количество конкатенаций неизвестно во время компиляции.
Ужас Кодирования имеет хорошую статью относительно этого вопроса, Печальная Трагедия Театра Микрооптимизации .
Лично я использую StringBuilder, когда у меня есть больше, чем всего одна или две строки для конкатенации. Я не уверен, существует ли реальный хит производительности, который будет получен, но я всегда читал и говорился, что выполнение регулярной конкатенации с несколькими строками создает дополнительную копию строки каждый раз, когда Вы делаете это, в то время как использование StringBuilder сохраняет одну копию, пока Вы не называете финал ToString()
метод на нем.
Кто-то выяснил экспериментально, что критическое число равняется 6. Больше чем 6 конкатенаций подряд и необходимо использовать StringBuilder. Не может помнить, где я нашел это.
Однако примечание это, если Вы просто пишете это в строке:
"qwert" + "yuiop" + "asdf" + "gh" + "jkl;" + "zxcv" + "bnm" + ",."
, Который преобразовывается в один вызов функции (я не знаю, как записать это в VB.net)
String.Concat("qwert", "yuiop", "asdf", "gh", "jkl;", "zxcv", "bnm", ",.");
Поэтому при выполнении всех конкатенаций на одной строке, затем не беспокойтесь StringBuilder потому что Строка. Concat эффективно сделает все конкатенации сразу. Это - только если Вы делаете их в цикле или последовательно конкатенируете.
Мое правило - когда Вы добавите к строке в Для или Цикл foreach, используйте StringBuilder.