logo
volkov / C++ / Бьерн Страуструп-Справочное руководство по С++

R.7.1.1 Спецификации класса памяти

Спецификации класса памяти могут быть такие:

спецификация-класса-памяти:

auto

register

static

extern

Спецификации auto и register могут применяться только для

имен объектов, которые описаны в блоке ($$R.6.3), или для формальных

параметров ($$R.8.3). Почти всегда спецификация auto избыточна и

используется не часто, так, auto используется, чтобы явно отделить

оператор-описание от оператора-выражения ($$R.6.2).

Описание register является описанием auto, которое подсказывает

транслятору, что описываемые переменные будут использоваться

достаточно интенсивно. Подсказка может быть проигнорирована, и во

многих реализациях она игнорируется в том случае, когда берется

адрес переменной.

Описание объекта считается определением, если только оно не

содержит спецификации extern и инициализации ($$R.3.1).

Определение приводит к выделению памяти соответствующего

размера и выполнению соответствующей инициализации ($$R.8.4).

Спецификации static и extern могут применяться только к именам

объектов или функций или к анонимным объединениям. Внутри блока

недопустимы описания функций со спецификацией static или

формальных параметров со спецификацией static или extern.

Статические члены класса описываются в $$R.9.4. Спецификация

extern недопустима для членов класса.

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

Объекты, описанные как const, подлежат внутреннему связыванию,

если только они не были описаны с внешней связью. Имя со

спецификацией extern подлежит внешнему связыванию, если только ранее

оно не было описано с внутренней связью. Имя с файловой областью

видимости и без спецификации-класса-памяти подлежит внешнему

связыванию, если только ранее оно не было описано с внутренней

связью или со спецификацией const. В смысле связывания для функций,

не являющихся членами, спецификация inline эквивалентна static

($$R.3.3). Для одного имени все его спецификации, определяющие

связывание, должны быть согласованы. Например,

static char* f(); // f() имеет внутреннее связывание

char* f() // f() все еще внутреннее

{ /* ... */ }

char* g(); // g() имеет внешнее связывание

static char* g() // ошибка: противоречие в связывании

{ /* ... */ }

static int a; // `a' имеет внутреннее связывание

int a; // ошибка: второе определение

static int b; // `b' имеет внутреннее связывание

extern int b; // `b' все еще внутреннее

int c; // `c' имеет внешнее связывание

static int c; // ошибка: противоречие в связывании

extern int d; // `d' имеет внешнее связывание

static int d; // ошибка: противоречие в связывании

Имя неопределенного класса можно использовать в описании

extern. Однако, такое описание нельзя использовать прежде, чем

класс будет определен, например,

struct S;

extern S a;

extern S f();

extern void g(S);

void h()

{

g(a); // ошибка: S неопределено

f(); // ошибка: S неопределено

}