Значения constexpr вызывают увеличение размера двоичного файла? - PullRequest
0 голосов
/ 04 августа 2020

Я знаю, что типизированные типы, такие как нижеприведенные, ничего не стоят по размеру скомпилированного двоичного файла: думаю, я хочу использовать integral_constant s по этой причине, поскольку у них есть член ::value. Я могу обойтись чем-то более похожим на:

template<typename ValHolder>
struct Deducer;

template<auto value>
struct Deducer<ValueHolder<value>> {
    using Output = ValueHolder<value+1>;
};

Но это определенно немного больше работы, поэтому я хочу убедиться, что делаю это не зря. Обратите внимание, что мы говорим о ТОННАХ таких значений (я бы объяснил, но я не хочу, чтобы go слишком сильно касалось; я, вероятно, получил бы больше комментариев на тему «должен ли я заниматься проектом», чем на вопрос !).

Итак, возникает вопрос: принимают ли значения [static] constexpr какой-либо размер в скомпилированном двоичном файле или значения заменяются во время компиляции, как если бы они были введены буквально? Я почти уверен, что они ДЕЙСТВИТЕЛЬНО принимают размер в двоичном файле, но я не уверен.

Я провел небольшой тест на godbolt, чтобы посмотреть на сборку constexpr и non-constexpr стороны массива - рядом, и все выглядело очень похоже на меня: https://godbolt.org/z/9hecfq

int main()
{
    // Non-constexpr large array
    size_t arr[0xFFFF] = {};

    // Constexpr large array
    constexpr size_t cArr[0xFFF] = {};

    // Just to avoid unused variable optimizations / warnings
    cout << arr[0] << cArr[0] << endl;
    return 0;
}

Ответы [ 2 ]

3 голосов
/ 04 августа 2020

Это полностью зависит от:

  1. того, насколько компилятору хочется оптимизировать переменную.
  2. Как вы используете переменную.

Учитывайте опубликованный вами код. Вы создали массив constexpr. Поскольку это массив, его 100% законно проиндексировать со значением времени выполнения. Это потребовало бы, чтобы компилятор выдал код, который обращается к массиву по этому индексу, что потребует, чтобы этот массив фактически существовал в памяти. Поэтому, если вы используете его таким образом, он должен иметь хранилище.

Однако, поскольку ваш код индексирует этот массив только с постоянным индексом выражения, компилятор, который хочет немного подумать более чем -O0 позволит понять, что он знает значение всех элементов в этом массиве. Таким образом, он точно знает, что такое cArr[0]. А это означает, что компилятор может просто преобразовать это выражение в правильное значение и просто проигнорировать существование cArr.

Такой компилятор может сделать то же самое с arr, BTW; это не обязательно должно быть постоянным выражением, чтобы компилятор обнаружил отсутствие операции.

Также обратите внимание, что, поскольку оба массива не являются статическими c, ни один из них не будет занимать память »в скомпилированном двоичный ". Если для них требуется хранилище времени выполнения, это будет пространство стека, а не пространство для исполняемых файлов.

В общих чертах, переменная constexpr займет хранилище на любом разумном уровне оптимизации, если вы сделаете что-то, что требует . занимает место в памяти. Это может быть что-то столь же безобидное, как передача его в (не встроенную) функцию, которая принимает параметр const&.

0 голосов
/ 04 августа 2020

Спросите своего компоновщика :) Нигде в стандарте C ++ нет ничего, что могло бы повлиять на ответ. Таким образом, вы, безусловно, должны создать свой код в режиме выпуска и проверить, увеличивает ли в конкретном сценарии использования размер или нет.

Любые общие результаты, которые вы получите на других платформах, разные компиляторы (1), другие параметры компиляции, другие модули, добавленные / удаленные в ваш проект, или даже любые изменения в коде не будут иметь большого значения.

У вас есть specifici c вопрос, который зависит от стольких факторов, что общие ответы ИМХО бесполезны. быть уже в вашем наборе тестов / бенчмарков, у вас должны быть сбой сборки интеграции, когда что-то растет, а не должно, et c. Никакие измерения и автоматизация не являются prima fa cie свидетельством того, что вам на самом деле все равно .

Итак, поскольку вы, вероятно, заботитесь о размере двоичного файла, просто напишите код, который вы имели в виду, и посмотрите на панели управления CI двоичный размер metri c. О, у тебя его нет? Что ж, это первое, что нужно сделать, прежде чем вы продолжите go. Я серьезно.

(1): Тот же компилятор = тот же двоичный файл. Вы говорите, я сумасшедший? Нет. Он укусил меня слишком часто. Если двоичный файл компилятора отличается (кроме меток времени), это не тот же компилятор, конец истории.

...