Выделена ли память для статической переменной const, адрес которой никогда не используется? - PullRequest
8 голосов
/ 28 ноября 2011

Если я никогда не использую адрес статической переменной const, выделяется ли для нее память при использовании достаточно современного компилятора?

Ответы [ 4 ]

10 голосов
/ 28 ноября 2011

Это зависит от типа переменной и от того, означает ли «константа» также «константное выражение». Пример:

static const Foo = get_foo(std::cin);

static const int q = argc * 3;

static const std::string s(gets());

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

С другой стороны, следующая константа выражение может никогда не иметь физической памяти:

static const int N = 1000;

static const std::shared_ptr<void> vp();  // constexpr constructor!

Самое главное, статические переменные constexpr member не нуждаются в определении, если вы осторожны:

struct Bar
{
  int size() const { return N; }
  static const int N = 8;
};
// does NOT need "const int Bar::N;"
3 голосов
/ 28 ноября 2011

Есть вероятность, что это не так, но это не имеет значения.Вы не можете полагаться на детали реализации, только на стандарт.

1 голос
/ 28 ноября 2011

Память для глобальных переменных зарезервирована компоновщиком, а не компилятором. Поэтому вопрос заключается в том, достаточно ли умен компоновщик, чтобы не резервировать место для глобальных переменных, которые используются только значением.

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

Сказав это, стандарт определяет, можете ли вы оптимизировать статическое хранилище (3.7.1.2: [basic.stc.static]):

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

Так что если статическая переменная const имеет конструктор или деструктор, ее нельзя оптимизировать (хотя некоторые компиляторы / компоновщики будут делать это в любом случае). Если нет, то может. Будет ли это зависеть от компоновщика.

1 голос
/ 28 ноября 2011

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

В дополнение к ограничениям, которые Kerrek SB упоминает, хранилище для значения const expr может быть исключено, если само значение никогда не используется во время выполнения.

Это не обязательно означает, что значение не нужно оценивать - если статическое const expr использовалось только как условие ветвления, это условие может оцениваться статически, а другие пути кода могут не генерироваться или могут быть исключены оптимизатором.

Практически любое хранилище с продолжительностью static может быть исключено, если реализация может гарантировать поведение, как если бы хранилище присутствовало - т.е. выражение сравнения, которое может быть оценено во время компиляции - как другое const expr, сравнение указателя где известно, что rhs - это псевдоним другой переменной или, возможно, несовместимый тип. Это также может быть исключено, если значение считывается только в переменные, которые сами никогда не читаются; или где значение может быть уменьшено до const expr.

struct Foo{};
static Foo bar; // static instance

Foo* func() {
    if ( ! (&bar) ) { // always non-NULL
        // this block may be eliminated
        Foo* myCopy(new Foo(bar));
        return myCopy;
    }
    // so 'bar' is never referred to, and we know it has no side-
    // effects, so the static variable can be eliminated
    return new Foo();
}

3.7.1 Статическая продолжительность хранения

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

...