Подтвердить что ты не робот

Какая разница между статическими константными и статическими встроенными переменными в С++ 17?

С С++ 17 мы получаем встроенные переменные.

Одним из способов их использования является определение константных полей в классах.

Так в чем же разница между этими двумя постоянными определениями:

class MyClass {
    static constexpr int myFirstVar = 10;
    static const inline int mySecondVar = 100;
};

Конечно, constexpr делает myFirstVar неявно встроенным.

Какой лучший выбор здесь, использовать constexpr или inline?

Примечание: когда вам не нужна константность, тогда inline делает это проще. С constexpr вас нет такого выбора.

4b9b3361

Ответ 1

Вам не нужно указывать инициализатор для mySecondVar в точке объявления. Инициализатор не должен сам constexpr.

Это означает, что если мы попытаемся определить myFirstVar следующим образом:

class MyClass {
    static constexpr int myFirstVar;
};

int MyClass::myFirstVar = 1;

Или вот так:

#include <cstdlib>

class MyClass {
    static constexpr int myFirstVar = rand();
};

Он плохо сформировался в любом случае. constexpr семантика требует этого и по уважительной причине.

Подход спецификатора inline позволяет включать определение статической переменной в самом заголовке, без инициализатора constexpr; или если инициализатор довольно сложный, он не обязательно должен быть в самом определении класса.

Итак, это вполне допустимый заголовок в С++ 17:

#include <cstdlib>

class MyClass {
    static const int mySecondVar;
};

inline const int MyClass::mySecondVar = rand();

Стандартная promises нас, что все единицы перевода, содержащие заголовок, будут видеть одно и то же значение для переменной, хотя мы не будем знать, что это такое до выполнения.

В основном это инструмент для библиотек. Предположим, что ваша библиотека - только заголовок. Тогда, в прежние дни, каковы были ваши варианты, если вам нужна статическая константа, определенная так?

Ну, у вас может быть объектный файл, загруженный с вашей библиотекой. Он будет скомпилирован из единицы перевода, содержащей только постоянное определение. Теперь библиотека не только для заголовка.

Или вы можете полагаться на встроенные функции. Встроенный переменный эффект может быть достигнут с помощью следующего:

class MyClass {
    static inline int mySecondVar();
};

inline int MyClass::mySecondVar() {
  static const int value = rand();
  return value;
}

Но он скрыт за стенкой синтаксиса и маскирует то, что по существу является константой, с оператором вызова функции.