Какая разница между внешней переменной какой-либо переменной и статической переменной?Разница между внешней переменной какого-либо типа и статической переменной
//ClassA.m
NSString *var1;
static NSString *var2;
@implementation ClassA
...
Какая разница между внешней переменной какой-либо переменной и статической переменной?Разница между внешней переменной какого-либо типа и статической переменной
//ClassA.m
NSString *var1;
static NSString *var2;
@implementation ClassA
...
extern
постоянная/переменная, которая одно определение может (или ссылки) через несколько объектных файлов. Это глобальный, экспортированный символ C. Используйте это, если вы хотите получить доступ к константной/глобальной переменной из нескольких единиц перевода (или скомпилированных файлов) или если вы хотите использовать его в нескольких двоичных файлах (например, вы хотите использовать его из своего приложения, а определение - в динамической библиотеке). Обычно вы объявляете это в заголовке для других пользователей.
The static
выдает копию для каждого перевода. Каждый файл, который скомпилирован, который также видит (например, #include
d), статичный будет выдавать копию этого статического элемента. Вы должны избегать этого. Это приведет к раздутой бинарности, которая имеет очень запутанное выполнение. Вы должны одобрить статичность, если значение является локальным для файла и должно быть закрыто для этого файла.
По этим причинам вы должны поддержать static
в ваших файлах .c, .m, .cpp и .mm и extern
в ваших заголовках.
Наконец, что NSString
указатель должен быть const
по умолчанию:
// declaration - file.h
extern NSString * const var1;
// definition - file.m
NSString * const var1 = @"var1";
или
static NSString * const var2 = @"var2";
Если вы все еще хотите больше, here's a related answer I wrote и here's another.
Я мог бы дать объяснение, но это не так хорошо, как это:
http://blog.ablepear.com/2010/01/objective-c-tuesdays-static-variables.html
Глобальные переменные и static
Объявление переменной вне любого метода (и в Objective-C либо внутри, либо снаружи, @implementation
/@end
делает срок службы из переменной глобальной, которая является переменной будет существовать в течение всего периода времени, когда приложение выполняется.
глобальной переменной, без квалификации, или только с const
и/или volatile
классификаторов, является видимым откуда угодно. Так, например:
NSString *MyApplicationName;
объявляет глобальную переменную MyApplicationName
, которые могут быть доступны из любого места в приложении.
Видимость глобальной переменной (но не ее жизненного цикла) может быть ограничена только файлом (точнее «единиц компиляции», позволяющим использовать один файл, включая другие), содержащий объявление, путем присвоения ему static
.Так, например:
static NSString *MyClassName;
объявляет глобальную переменную MyClassName
, которая видна только в текущем модуле компиляции.
Использование static
квалифицированных глобальных деклараций в пределах @implementation
/@end
- это самое близкое, что Objective-C предлагает переменные класса «другие языки» других языков.
Вы не должны место глобальные переменные декларации, static
квалификацию, или нет, в заголовочных файлах, которые приводят к нескольким различным декларациям - ошибка приведет, если нет static
классификатор, а также несколько различных переменных с различными видимости областей если есть.
extern
отборочные
extern
отборочные делает что-то, а другое.
Первоначальное значение (небольшая релаксация теперь разрешено, смотри ниже), чтобы просто определить тип и имя глобальной переменной которая объявлена в другом месте. То есть вы сообщаете компилятору: «существует глобальная переменная некоторого типа и имени, которое я хотел бы использовать, который будет предоставлен другой единицей компиляции». Например:
extern NSString *MyApplicationName;
утверждает, что некоторые модули компиляции содержит декларацию (которая не должен быть static
квалифицированы):
NSString *MyApplicationName;
extern
квалифицирована декларация сам по себе не вызывает выделение какого-либо хранилищ для глобального переменная.
Место extern
квалифицированных деклараций в заголовочных файлах, это то, как единица компиляции рекламирует глобальные переменные, которые она хочет экспортировать. Вы также можете поместить их в файлы кода для ссылки на глобальные переменные, объявленные в другом месте. Внутри файла кода вы можете разместить квалифицированную декларацию extern
вне любого метода/функции - в этом случае имя/тип доступно для всей единицы компиляции - или внутри метода/функции - и в этом случае видимость имени/тип ограничивается только этим методом/функцией.
Небольшой релаксация
Первоначально вы должны были иметь одну не- заявления extern
квалификатора, чтобы удовлетворить любые extern
квалифицированных из них. Однако это было позже изменено, если при объединении различных единиц компиляции ни одна из них не объявляет глобальную переменную, на которую ссылается некоторая extern
квалифицированная декларация, тогда компоновщик (обычно?) Просто генерирует эту переменную и добавляет ее в результирующий двоичный файл, а не создает «Отсутствует глобальная» ошибка. Лучшая практика программирования заключается не в том, чтобы полагаться на это расслабление - всегда есть не-extern
квалифицированное объявление для каждой глобальной переменной.
Можно утверждать, что это тонкая точка, но квалификатор 'extern' сам не объявляет переменную глобальной видимостью (« linkage »выше) - глобальная переменная без' extern' имеет глобальную видимость. Однако, если вы решите относиться к нему так, как если бы вы, вероятно, не ошибетесь. Дальнейшие подробности в моем ответе. – CRD
@CRD хорошая точка (+1), и хороший ответ (+1). мой ответ дает введение в тему. я избегал упоминания переменных без квалификации, потому что для них нет практического использования (ну, я предпочитаю явную квалификацию ...). – justin
зависит от того, как вы определяете «практический». Хорошим шаблоном для глобалов является одно не-«внешнее» квалифицированное определение в файле кода, которое предоставляет глобальную и одну или несколько объявлений с «extern», которые ссылаются на глобальные. То есть эквивалентный шаблон для методов/функций - одно место определяет тело, одно или несколько мест ссылаются на метод/функцию с прототипом. В обоих случаях «один или несколько» часто означает только заголовок для файла кода, который определяет глобальную/метод/функцию. Теперь релаксация * позволяет * добавить 'extern' в def, но это не имеет смысла. – CRD