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.
Заказ:
Один тип может быть более квалифицированным, чем другой:
- Ни один cv-квалификатор не меньше квалификатора const
- Ни один cv-квалификатор не может быть меньше квалификатора volatile
- Ни один cv-квалификатор не меньше квалификатора const-volatile
- Квалификатор const меньше квалификатора const-volatile
- квалификатор volatile меньше квалификатора const-volatile
Еще не решено, имеют ли 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"
Функция-член 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. Они влияют на продолжительность жизни (продолжительность), место и способ использования переменных в приложении.