Статические переменные в C и C ++

Если вы получаете эту ошибку при попытке вставить карту Google в iframe, вам нужно добавить &output=embed к исходной ссылке.

16
задан Naveen 27 March 2010 в 07:03
поделиться

5 ответов

Нет, в этом отношении нет разницы между C и C ++.

Прочтите этот SO-ответ о том, что static означает в программе на языке C. В C ++ есть несколько других значений, связанных с использованием static для переменных класса (вместо переменных экземпляра).

Что касается глобальных переменных, которые статичны - только с точки зрения распределения памяти (они выделяются в сегменте данных, как и все глобальные переменные). С точки зрения видимости:

static int var;    // can't be seen from outside files
int var;           // can be seen from outside files (no 'static')
16
ответ дан 30 November 2019 в 17:52
поделиться

Здесь есть два понятия: «статическая ссылка (или область действия)» и статическое распределение ».

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

7
ответ дан 30 November 2019 в 17:52
поделиться

C и C ++ одинаковы.

static делает две разные вещи.

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

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

Последнее, что делает static, - это изменяется при запуске инициализатора (т.е. int foo = 5) для переменной. Для всех случаев, когда распределение является глобальным (каждый случай, кроме автоматического), инициализатор запускается только один раз, в начале выполнения вашей программы.Он запускается даже до запуска main (), поэтому вы можете получить не совсем ожидаемый результат, если ваш инициализатор не просто постоянное число, а запускает некоторый код. В автоматическом случае инициализатор запускается каждый раз, когда вводится функция, и в этом случае он всегда выполняется после ввода main ().

5
ответ дан 30 November 2019 в 17:52
поделиться

Я хочу добавить к ответу Southern Hospitality Статические переменные в C и C ++

следующие примечания:

Использование static для обозначения "локально для единицы перевода" не рекомендуется в C ++ (href = "https: // rads.stackoverflow.com/amzn/click/com/0201700735 "rel =" nofollow noreferrer "Язык программирования C ++: специальный выпуск, приложение B.2.3, устаревшие функции).

Вместо этого следует использовать безымянные пространства имен:

static int reply = 42; // deprecated

namespace {
    int reply1 = 42;  // The C++ way
}

Как уже По заявлению Southern Hospitality, порядок инициализации глобальных объектов не определен. В этой ситуации вам следует рассмотреть возможность использования шаблона Singleton href = "http://en.wikipedia.org/wiki/Singleton_pattern#C.2B.2B" .

ОБНОВЛЕНИЕ: GMan прокомментировал мой ответ:

«Порядок определяется для каждой единицы перевода, ...»: Это действительно вылетело у меня из головы, поэтому я поискал его на языке программирования C ++ .

В Разделе 9.4.1, «Инициализация нелокальных переменных», профессор Страуструп предполагает, что «функция, возвращающая ссылку, является хорошей альтернативой глобальной переменной»:

int& use_count()
{
        static int uc = 0;
        return uc;
}

«Вызов use_count ( ) теперь действует как глобальная переменная, которая инициализируется при первом использовании. Например: «

void f()
{
        std::cout << ++use_count() << '\n';
}

В моем понимании это очень похоже на шаблон Singleton.

GMan прокомментировал дальше:« Нам нужно ограничить нашу способность создавать эти объекты одним и предоставить глобальный доступ к нему ». ограничение одним действительно относится к чему-либо в проблеме? Он может понадобиться нам глобально, но кто сказал, что мы не хотим этого в других местах? »

Некоторые цитаты из Синглтона (127) (Gamma et al, Design Patterns ):

«Шаблон Singleton является улучшением по сравнению с глобальными переменными. Он позволяет избежать загрязнения пространства имен глобальными переменными, которые хранят отдельные экземпляры.»

«Шаблон позволяет легко изменить свое мнение и разрешить более одного экземпляра. класса Singleton.«

Синглтоны инициализируются в том порядке, в котором они используются впервые.

В Херб Саттер, Андрей Александреску, Стандарты кодирования C ++, пункт 10 говорит:

« Избегайте общих данных, особенно глобальных данных ».

Поэтому Я часто использую синглтоны, чтобы избежать глобальных данных. Но, конечно, поскольку все слишком часто используется, это могло быть чрезмерным использованием шаблона синглтона. (Джошуа Кериевский называет это «синглтоном» в своей книге «Рефакторинг для шаблонов».)

ОБНОВЛЕНИЕ 2:

(Извините, но я не могу писать комментарии, поэтому это Обновление.)

Джалф написал в своем комментарии: «Банда из четырех человек курила что-то незаконное, когда писала о шаблоне синглтона».

Очевидно, , другие разработчики C ++ тоже курили интересные вещества. Например, Херб Саттер (он более десяти лет служил секретарем и председателем комитета стандартов ISO C ++ во время разработки второго стандарта C ++, C ++ 0x, и в качестве ведущего архитектора C ++ / CLI в Microsoft. В настоящее время Херб является разработчиком модели памяти Prism для Mic платформы rosoft и расширения Concur для Visual C ++ для параллельного программирования), написано в C ++ Coding Standards, Item 21:

«Когда вам нужна такая переменная (уровня пространства имен), которая может зависеть от другой, рассмотрите шаблон проектирования Singleton; При осторожном использовании он может избежать неявных зависимостей, гарантируя, что объект инициализируется при первом доступе. Тем не менее, синглтон - это глобальная переменная в овечьей шкуре, и ее нарушают взаимные или циклические зависимости »

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

Обратите внимание, что в языке Java глобальные данные даже не существуют. Очевидно,глобальные данные заменяются / эмулируются с использованием шаблона проектирования Singleton.

(Поскольку я работаю в своей повседневной работе с командой Java, я стремлюсь к максимальному сходству моих программ на C ++ с программами Java. Например, каждый класс расположен в своем собственном исходном файле / блоке перевода.)

{ {1}}
1
ответ дан 30 November 2019 в 17:52
поделиться

На самом деле это не прямой ответ на ваш вопрос, но что-то тесно связанное, на что следует обратить внимание, если вы используете как C, так и C++.

В C++, в отличие от C, глобальные переменные, объявленные "const", являются неявно локальными для единицы трансляции, как если бы использовалось "static".

Пример:

// file A
extern const int glob;

// file B
const int glob = 42;

Это будет работать, если вы используете компилятор C, но не компилятор C++. В C++ переменная glob в файле B не может быть использована из файла A, и компоновщик сгенерирует ошибку «неразрешенная ссылка».

1
ответ дан 30 November 2019 в 17:52
поделиться