Хорошо, чтобы объявить статическую глобальную переменную.H-файл?

ключевое слово static сохраняет область глобальной переменной, ограниченную этой единицей перевода. Если я использую static int x в a .H-файл и включить этот .H файл каждый другой файл, не все ли они принадлежат к одной и той же единице перевода? Тогда разве x не будет виден повсюду? Так какова же роль статики сейчас?

кроме того, есть ли какое-либо использование static const int x ,где X-глобальная переменная? Разве не все глобальные переменные const статичны по умолчанию? И область действия переменной const ограничена TU, даже если он ограничен в цикле for в файле?

6 ответов


если вы пишите

static const int x

на .h файл, то каждый блок перевода, что #include-это .h будет иметь свою собственную частную переменную x.

если вы хотите иметь 1 глобальную переменную, видимую всем, вы должны написать

extern const int x;

на .h файл и

const int x = ...;

в одном из .cpp файлы.

если вы хотите иметь статический const int видимым для только одна единица перевода - не упоминайте об этом в .h файлов.


Если я использую статический int x в a .H-файл и включить этот .H каждый файл другой файл, разве все они не принадлежат к одной и той же переводческой единице?

Если вы объявляете что-то как статическое (не внутри класса, поскольку ключевое слово class static имеет другую семантику), эта статическая переменная не может быть видна вне ее TU. Поэтому, помещая его в файл заголовка, каждый TU, включая этот заголовок, будет иметь другую частную копию этой статической переменной.

и область видимости переменной const ограничена TU, даже если она ограничена в цикле for в файл?

нет. Даже для статического значения const область определяется его объявлением. Таким образом, область будет ограничена вашими скобками.


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

вы можете объявить const int на namespace блок, то это нормально.


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

если вы не используете адрес const переменная любой современный компилятор должен иметь возможность просто использовать значение и оптимизировать саму переменную. В таком случае static const-квалифицированная переменная полностью в порядке.


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


"static global" не имеет смысла, они в некотором роде противоположны друг другу.

термин "глобальный" часто неправильно используется для описания переменной, объявленной вне любой функции в объем файла. Но скорее глобальная переменная-это одна с внешняя связь, к которому может получить доступ любой файл в проекте-следовательно, глобальный.

противоположность внешней связи внутренняя перелинковка, что означает, что переменная может получить только доступ к ЕП где он объявлен. Единица перевода, означающая один .c файл и все заголовки, включенные в него (рекурсивно).

static является гарантией того, что переменная получает внутреннюю связь. Таким образом, другой перевод не сможет получить к нему доступ или объявить extern переменные, относящиеся к нему.

что произойдет, если объявить static переменная в заголовочном файле - это то, что несколько единиц перевода получат отдельную переменную с таким именем. Код будет компилироваться нормально, хотя умные компоновщики заметят это и дадут ошибку компоновщика. Такие ошибки компоновщика часто не описательны и их трудно отследить.

это приводит нас к следующим рекомендациям:

  • не объявить любой переменные в заголовочном файле, как это часто создает тонкие ошибки и ошибки компоновщика.
  • чтобы предотвратить такие ошибки, всегда окружайте все заголовочные файлы " header охранники":

    #ifndef MYHEADER_H 
    #define MYHEADER_H 
      /* contents of header */ 
    #endif
    
  • все переменные, объявленные в области файла, должны быть объявлены static, для личного заключения и не загромождают пространство. Аналогично,extern следует избегать, так как это приводит к плохому дизайну и программированию спагетти.