C ++

Квалификаторы C ++ и спецификаторы классов хранения

Квалификаторы C ++ и спецификаторы классов хранения

CV расшифровывается как Constant-Volatile. Объявление объекта, которому не предшествуют const и / или volatile, является cv-неквалифицированным типом. С другой стороны, объявление объекта, которому предшествуют const и / или volatile, является типом с квалификацией cv. Если объект объявлен как const, значение в его расположении не может быть изменено. Неустойчивая переменная - это переменная, значение которой находится под влиянием программиста и, следовательно, не может быть изменено компилятором.Спецификаторы класса хранения относятся к жизни, месту и способу существования типа. Спецификаторы класса хранилища - статические, изменяемые, thread_local и extern.

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

Содержание статьи:

Отборочные:

const

Объект, объявленный константой, - это объект, хранилище (местоположение) которого не может быть изменено. Например, в заявлении:

int const theInt = 5;

Значение 5 в хранилище для theInt не может быть изменено.

летучий

Рассмотрим следующее утверждение:

int portVal = 26904873;

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

int volatile portVal;
portVal = 26904873;
или как:
int volatile portVal = 26904873;

Сочетание const и volatile:

const и volatile могут встречаться в одном операторе следующим образом:

int const volatile portVal = 26904873;

cv-квалификаторы

Переменная, которой предшествуют const и / или volatile, является типом с квалификацией cv. Переменная, перед которой не указано ни const, ни volatile, ни то и другое, является неквалифицированным типом cv.

Заказ:

Один тип может быть более квалифицированным, чем другой:

Еще не решено, имеют ли const и volatile один и тот же ранг.

Массив и созданный объект:

Когда массив объявлен константой, как в следующем заявлении, это означает, что значение каждого элемента массива не может быть изменено:

const char arr [] = 'a', 'b', 'c', 'd';

Будь то 'a', 'b', 'c' или 'd', его все равно нельзя изменить на какое-либо другое значение (символ).

Аналогичная ситуация применяется к экземпляру объекта класса. Рассмотрим следующую программу:

#включать
используя пространство имен std;
класс Cla

общественность:
char ch0 = 'а';
char ch1 = 'б';
char ch2 = 'c';
char ch3 = 'д';
;
int main ()

const Cla obj;
возврат 0;

Из-за утверждения «const Cla obj;» с const в функции main () ни 'a', ни 'b', ни 'c', ни 'd' не могут быть изменены на какое-либо другое значение.

Спецификаторы класса хранения:

Спецификаторы класса хранения статические, изменяемые, thread_local и extern.

В статический указатель класса хранения

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

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

#включать
используя пространство имен std;
int funct ()

статический int stac = 10;
cout << stac < 50)

cout << '\n';
возврат 0;

funct ();

int main ()

funct ();
возврат 0;

Результат:

10 20 30 40 50

Если статическая переменная не инициализируется при ее первом объявлении, она принимает значение по умолчанию для ее типа.

Статический спецификатор также можно использовать с членами класса; использование здесь другое. Здесь он позволяет получить доступ к члену без создания экземпляра объекта.

Следующая программа иллюстрирует это для элемента данных:

#включать
используя пространство имен std;
класс Cla

общественность:
статическая константа int num = 8;
;
int main ()

cout << Cla::num << '\n';
возврат 0;

Результат:

8

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

Следующая программа иллюстрирует использование «статики» для функции-члена:

#включать
используя пространство имен std;
класс Cla

общественность:
статический метод void ()

cout << "Of static member function!" << '\n';

;
int main ()

Cla :: method ();
возврат 0;

Результат:

Статической функции-члена!

Обратите внимание, что использование оператора разрешения области видимости для доступа к статической функции-члену вне ее области видимости (в основной функции).

Изменяемый спецификатор

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

Следующая программа иллюстрирует это:

#включать
используя пространство имен std;
класс Cla

общественность:
char ch0 = 'а';
char ch1 = 'б';
изменяемый char ch2 = 'c';
char ch3 = 'д';
;
int main ()

const Cla obj;
объект.ch2 = 'z';
cout << obj.ch0 << " << obj.ch1 << " << obj.ch2 << " << obj.ch3 << " << '\n';
возврат 0;

Результат:

'а "б" г "д"

Спецификатор thread_local

При нормальном запуске программы выполняется один сегмент кода, затем следующий сегмент кода, за ним следует еще один сегмент кода и т. Д. Это одна нить; основной поток. Если два сегмента кода выполняются одновременно (одинаковой продолжительности), то требуется второй поток. Результат второго потока может быть даже готов до того, как основной поток.

Функция main () похожа на основной поток. Программа может иметь более двух потоков для такого асинхронного поведения.

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

Следующая короткая программа иллюстрирует использование спецификатора thread_local:

#включать
#включать
используя пространство имен std;
thread_local int inter = 1;
void thread_function ()

интер = интер + 1;
cout << inter << "nd thread\n";

int main ()

поток thr (& thread_function); // th начинает работать
cout << inter << "st or main thread\n";
чт.присоединиться(); // основной поток ожидает завершения потока
возврат 0;

Результат:

1-й или основной поток
2-й поток

Переменная inter, которой предшествует thread_local, означает, что inter имеет отдельный экземпляр в каждом потоке. И что он может быть изменен в разных потоках, чтобы иметь разные значения. В этой программе ему присваивается значение 1 в основном потоке и изменяется на значение 2 во втором потоке.

Потоку нужен специальный объект для работы. Для этой программы библиотека, включенная в "#include" »Имеет класс, называемый потоком, из которого был создан объект thr. Конструктор этого объекта принимает в качестве аргумента ссылку на функцию потока. Имя функции потока в этой программе - thread_function ().

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

Спецификатор extern

Проще говоря, для объявления память не выделяется для переменной или функции, в то время как для определения выделяется память. Зарезервированное слово extern позволяет объявить глобальную переменную или функцию в одном файле, но определить в другом. Такие файлы называются единицами перевода для всего приложения C ++.

Введите следующую программу и сохраните ее с именем файла mainFile:

#включать
используя пространство имен std;
int myInt;
const char ch;
void myFn ();
int main ()

myFn ();
возврат 0;

Переменная myInt, постоянная переменная ch и функция myFn () были объявлены без определения.

Введите следующую программу с определениями и сохраните ее с именем файла otherFile в том же каталоге:

#включать
используя пространство имен std;
int myInt = 10;
const char ch = 'c';
недействительным myFn ()

cout << "myFn() says " << myInt << " and " << ch <<'\n';

Попробуйте скомпилировать приложение в терминале (командная строка DOS) с помощью следующей команды и обратите внимание, что оно может не компилироваться:

основной файл g ++.cpp otherFile.cpp -o Complete.EXE

Теперь перед тремя объявлениями в mainFile поставьте слово «extern», как показано ниже:

extern int myInt;
extern const char ch;
extern void myFn ();

Повторно сохранить mainFile. Скомпилируйте приложение с помощью:

основной файл g ++.cpp otherFile.cpp -o Complete.EXE

(Вот как отдельные файлы для одного и того же приложения компилируются на C ++)

И он должен скомпилировать. Теперь запустите приложение, завершите.exe, и вывод должен быть:

myFn () говорит 10 и c

Обратите внимание, что с помощью «extern» постоянная переменная может быть объявлена ​​в одном файле, но определена в другом. При работе с объявлением и определением функции в разных файлах использование extern необязательно.

Когда использовать extern? Используйте его, когда у вас нет файлов заголовков с глобальными объявлениями.

«Extern» также используется с объявлениями шаблонов - см. Ниже.

Заключение:

Переменная, которой предшествуют const и / или volatile, является типом с квалификацией cv. Переменная, которой не предшествуют ни const, ни volatile, ни то и другое, является неквалифицированным типом cv.

Спецификаторы класса хранилища - статические, изменяемые, thread_local и extern. Они влияют на продолжительность жизни (продолжительность), место и способ использования переменных в приложении.

Топ-5 карт для захвата игр
Все мы видели и любили потоковые игры на YouTube. PewDiePie, Jakesepticye и Markiplier - лишь некоторые из лучших игроков, которые заработали миллионы...
Как разработать игру в Linux
Десять лет назад не многие пользователи Linux могли бы предсказать, что их любимая операционная система однажды станет популярной игровой платформой д...
Порты коммерческих игровых движков с открытым исходным кодом
Бесплатные игры с открытым исходным кодом и кроссплатформенные версии игрового движка можно использовать для игры как в старые, так и в некоторые из с...